2013-06-19 132 views
4

我有5個項目,每個都有一個id和陣列

{ _id: ObjectId("51c21bec162c138d9d0001a7"), 
    tags: [ { name: "a", type: "tag" }, { name: "b", type: "tag" }, { name: "c", type: "note" } ] 
} 
{ _id: ObjectId("51c21ca22c69904840000178"), 
    tags: [ { name: "a", type: "tag" }, { name: "d", type: "tag" }, { name: "c", type: "note" } ] 
} 
{ _id: ObjectId("51c21cc1478cf6691a0001b4"), 
    tags: [ { name: "d", type: "tag" }, { name: "b", type: "tag" }, { name: "c", type: "note" } ] 
} 
{ _id: ObjectId("51c22292162c13b1ff000222"), 
    tags: [ { name: "a", type: "tag" }, { name: "d", type: "tag" }, { name: "e", type: "note" } ] 
} 
{ _id: ObjectId("51c222e926d602a57d0001d8"), 
    tags: [ { name: "a", type: "tag" }, { name: "d", type: "note" }, { name: "c", type: "note" } ] 
} 

這裏的目標是要返回的有標籤的所有項目的集合「項目」 'a'和'd',其中標籤的類型爲'tag'。你可能認爲這會做到這一點:

find({"tags.name":{"$all":["a","d"]}, "tags.type":'tag'}) 

返回3個文檔,這是不對的,但我已經瞭解到,這個查詢請求也一個或。因此,我嘗試使用'$ elemMatch'來做到這一點,我認爲這是最直觀的方式,但

find({"tags":{"$elemMatch":{'name':{'$all':["a","d"]}, "type":'tag'}}}) 

返回沒有文檔。

同樣的查詢,如果我只想要標記的項目「A」的作品:

find({"tags":{"$elemMatch":{'name':{'$all':["a"]}, "type":'tag'}}}) 

大概是因爲$所有被映射到類似$ EQ。

後來我發現,以下是我需要爲我最初的目標做:

find({"tags":{"$all":[{'$elemMatch':{'name':"a", "type":'tag'}}, {'$elemMatch':{'name':"d", "type":'tag'}} ]}}) 

返回更正兩個文檔。

但是這個語法太可怕了!我必須將我自己的數組[[a],「d」]擴展到查詢中。如果我正在編寫通用查詢引擎,並且我想說嵌入式文檔的多個字段是數組,並且我想要每個數組中的某個值的子集,那該怎麼辦?

有沒有更好的方法來做到這一點?更好的語法?

+0

在你的問題是不是真的清楚你的目標是什麼... *「我有這個5號文件,我想提取具有所有文件{...} 「*用您的實際目標替換{...} – thermz

+0

我更新了原始問題以使目標更清晰。對不起! – rahuldave

回答

2

你最終到達的是正確的解決方案。以編程方式構造$elemMatch規則的數組可能是一種改進。

考慮以下蟒蛇:

match_rules = [] 
for tag in query_tags: 
    match_rules.append({ 
    '$elemMatch': { 
     'name': tag 
     'type': 'tag' 
    } 
    }) 

collection.find({"tags":{"$all": match_rules}}) 
+0

它爲我工作!我有一個有點不同的情況,在子文檔(應用程序)數組中存在一些子文檔(轉換)。如果沒有特定用戶的應用程序轉換,我想要返回文檔。我可以做到這一點通過下面的查詢: { '轉變':{ $不是:{ $所有: { 應用:{ $ elemMatch:{ 用戶:用戶id } } } ] } } } – gmartini20