【问题标题】:How to get exact document result from key value type of embedded documents如何从嵌入文档的键值类型中获取准确的文档结果
【发布时间】:2013-05-08 12:33:08
【问题描述】:

假设我有这种结构化的文档,属性字段将是嵌入的文档 我已经索引了 attributes.key 和 attributes.value

1-------------------------------------------------------------------------------------
{ 
  "_id" : ObjectId( "5191d8e5d00560402e000001" ),
  "attributes" : [ 
  { "key" : "pobox","value" : "QaKUWo" }, 
  { "key" : "city", "value" : "CBDRip" }, 
  { "key" : "address","value" : "zmycAa" } ],
  "email" : "FWAUdl_2@email.com",
  "firstname" : "FWAUdl_2" 
}
2-------------------------------------------------------------------------------------
{ 
  "_id" : ObjectId( "5191d8e7d00560402e000055" ),
  "attributes" : [ 
    { "key" : "pobox", "value" : "sNFriy" }, 
    { "key" : "city", "value" : "JPdVrI" }, 
    { "key" : "address", "value" : "phOluW" } ],
  "email" : "hqYNWH_86@email.com",
  "firstname" : "hqYNWH_86" 
}

我的问题是如何在仅基于属性字段进行查询时获得准确的文档,

db.app.find({ attributes.key:address , attributes.value:/.*uw.*/i })

查询结果与我预期的不一样,它应该只产生第 2 个文档,而没有第 1 个文档。 我知道我将正则表达式放在 attributes.value 上,我希望它只检查具有地址值的 attributes.key。

如果我想过滤另一个键,比如,

db.app.find({ attributes.key:address , attributes.value:/.*uw.*/i , attributes.key:city , attributes.value:/.*ri.*/i })

任何意见都会对大家有所帮助。 谢谢。

【问题讨论】:

    标签: mongodb doctrine odm


    【解决方案1】:

    我猜你需要 $elemMatch (http://docs.mongodb.org/manual/reference/operator/elemMatch/)

    db.test123.find({ attributes : { $elemMatch : { 'key':"address" , 'value':/.*uw.*/i } } }).pretty()
    {
        "_id" : ObjectId("5191d8e7d00560402e000055"),
        "attributes" : [
            {
                "key" : "pobox",
                "value" : "sNFriy"
            },
            {
                "key" : "city",
                "value" : "JPdVrI"
            },
            {
                "key" : "address",
                "value" : "phOluW"
            }
        ],
        "email" : "hqYNWH_86@email.com",
        "firstname" : "hqYNWH_86"
    }
    

    【讨论】:

    • $elemMatch 运算符是否使用索引?我有一些方法可以使用 $where 运算符,检查属性列表中的所有项目,如下所示, db.mycollection.find({ $where : function() { for(var idx in this.attributes ){if(this.attributes[idx].key == 'address' && this.attributes[idx].value.match(/.*xl.*/i)){return true;}});但我认为这种方法不会使用索引。
    • 使查询使用索引,索引在:db.testing.ensureIndex({'attributes.key':1,'attributes.value':1})。还使用查询您的集合的旧样式,即 db.testing.find({ 'attributes.key':"address" , 'attributes.value' : "phOluW" } ).explain() 我大多听说 javascript 查询是通常很慢,现在不确定。
    • @KhalidAdisendjaja :只是一个小提示,尽管从我之前的评论中,我要求您使用旧式查询。但这不会导致您实际发布问题的重复问题,因为它这次尝试使用索引并进行正确匹配。遵循正则表达式也可以。 db.testing.find({ 'attributes.key':"address" , 'attributes.value' : /.*uw.*/i } ).explain()
    • @KhalidAdisendjaja :对索引部分感到抱歉,db.testing.find({ 'attributes.key':"address" , 'attributes.value' : /.*uw.*/i } )正在使用索引,但它在最后扫描文档并返回不需要的结果
    • No 不能使用常规查找查询,因为它会搜索另一个键不是“地址”的值对,我的选择是使用 $elemMatch 或 $where 运算符,只是好奇性能如果 $elemMatch 查询将使用进程上的索引(attributes.key,attributes.value)。
    【解决方案2】:

    刚刚调查了一下,发现了以下内容。下面使用下面提到的索引。您可以在 find() 上执行 explain() 以查看更多索引使用详情

    db.testing.getIndexKeys()
    [ { "_id" : 1 }, { "attributes.key" : 1, "attributes.value" : 1 } ]
    
    test:Mongo > db.testing.find({$and : [ { attributes : {$elemMatch : {key : 'address', value : /.*uw.*/i }} }, { attributes : {$elemMatch : {key : 'city', value : /.*ri.*/i }} }] }).pretty()
    {
        "_id" : ObjectId("5191d8e7d00560402e000055"),
        "attributes" : [
            {
                "key" : "pobox",
                "value" : "sNFriy"
            },
            {
                "key" : "city",
                "value" : "JPdVrI"
            },
            {
                "key" : "address",
                "value" : "phOluW"
            }
        ],
        "email" : "hqYNWH_86@email.com",
        "firstname" : "hqYNWH_86"
    }
    

    【讨论】:

    • 是的,我以为我也这样做了,猜猜这不是一个高性能的选项,但它确实有效,thx btw :)
    猜你喜欢
    • 2019-07-13
    • 2019-05-30
    • 1970-01-01
    • 2017-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多