mongodb $elemMatch查询返回所有子文档


db.aaa.insert({"_id":1, "m":[{"_id":1,"a":1},{"_id":2,"a":2}]})
db.aaa.find({"_id":1,"m":{$elemMatch:{"_id":1}}})
{ "_id" : 1, "m" : [ { "_id" : 1, "a" : 1 }, { "_id" : 2, "a" : 2 } ] }

使用$elemMatch作为查询操作符,它返回'm'中的所有子文档!!奇怪!

使用它作为项目操作符:

db.aaa.find({"_id":1},{"m":{$elemMatch:{"_id":1}}})
{ "_id" : 1, "m" : [ { "_id" : 1, "a" : 1 } ] }

这是好的。按照这个逻辑,在update中使用它作为查询操作符将更改'm'中的所有子文档。所以我这样做:

db.aaa.update({"_id":1,"m":{$elemMatch:{"_id":1}}},{$set:{"m.$.a":3}})
db.aaa.find()
{ "_id" : 1, "m" : [ { "_id" : 1, "a" : 3 }, { "_id" : 2, "a" : 2 } ] }

它以第二个例子(项目运营商)的方式工作。这让我很困惑。给我一个解释

这并不奇怪,这就是它的工作原理。

您正在使用$elemMatch 匹配文档中包含的数组中的元素。这意味着它匹配中的"文档"而不是"数组元素",所以它不只是有选择地只显示匹配的数组元素。

你能做的,以及你如何使用它与$set操作符,是使用一个位置$操作符来表示匹配的"位置"从你的查询端:

db.aaa.find({"_id":1},{"m":{$elemMatch:{"_id":1}}},{ "m.$": 1 })

这将只显示数组的一个元素。但是,在显示的结果中,*当然仍然是数组,并且不能将其强制转换为其他类型。

用法的另一部分是,这将只匹配一次。只有第一个匹配项才会被赋值给位置操作符。

所以也许最简洁的解释是你匹配"包含"你在查询中指定的子文档的属性的文档,并且不仅仅是"子文档"本身。

查看文档获取更多信息:

http://docs.mongodb.org/manual/reference/operator/projection/positional/http://docs.mongodb.org/manual/reference/operator/query/elemMatch/

最新更新