2013-05-14 44 views
0

假设我有这种文档结构,属性字段将是嵌入文档 ,并且我已经为属性.key和attributes.value编入索引如何从嵌入文档的键值类型获得确切文档结果

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

我的问题是,如何查询仅基于属性字段时得到确切的文件,

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

查询结果并不如我所料,这应导致只有第2文件只是没了第一次文件。 我知道我在attributes.value上设置了正则表达式,我期待它只检查具有地址值的attributes.key。

如果我要过滤的另一个关键,例如像什么,

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

任何意见将是有益的人。 Thx。

回答

0

只是调查了一点,想出以下。以下使用下面提到的索引。你可以在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" : "[email protected]", 
    "firstname" : "hqYNWH_86" 
} 
+0

是的,我以为我也这么做过,猜猜这不是一个高性能的选项,但它的工作原理,thx btw :) – 2013-05-15 12:21:27

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" : "[email protected]", 
    "firstname" : "hqYNWH_86" 
} 
+0

$ 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;}}); 但我认为这种方法不会使用索引。 – 2013-05-15 04:22:50

+0

使查询使用索引,索引:db.testing.ensureIndex({'attributes.key':1,'attributes.value':1})。也使用旧式的查询您的集合,即 db.testing.find({'attributes.key':“address”,'attributes.value':“phOluW”}).explain() 我大部分都听说过javascript查询通常很慢,现在还不确定。 – 2013-05-15 05:33:30

+0

@KhalidAdisendjaja:只是一个小记录,虽然从我之前的评论,我要求你使用旧式的查询方式。但是这不会导致您实际发布问题的重复问题,因为它会尝试这次使用索引并进行正确匹配。正则表达式也将工作。 db.testing.find({'attributes.key':“address”,'attributes.value':/.*uw.*/i}).explain() – 2013-05-15 05:37:06