2013-05-14 45 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