2013-06-19 92 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