$ elemMatch不能用新的mongodb 2.2吗?
在MongoDB的新版本中,我们可以使用$ elemMatch投影算子来限制查询对数组中单个匹配元素的响应。 http://docs.mongodb.org/manual/reference/projection/elemMatch/
但似乎在mongoose3没有工作,这里是例子:
{ _id: ObjectId(5), items: [1,2,3,45,4,67,9,4] } Folder.findOne({_id: Object(5)}, {$elemMatch: {$in: [1,67,9]}}) .exec(function (err, doc) { });
我期望得到以下文档:
{ _id: ObjectId(5), items: [1,67,9] }
但不幸的是,我得到的是与所有项目的文件:
{ _id: ObjectId(5), items: [1,2,3,45,4,67,9,4] }
这里的mongodb文档是误导性的,我们会让他们更新。
这就是说,你现在可以在你的投影中使用$ elemMatch,也就是你的字段select:
https://gist.github.com/3640687
另见: https : //github.com/learnboost/mongoose/issues/1085
[编辑]请求发送的文档: https : //github.com/mongodb/docs/pull/185
首先,您在$ elemMatch运算符前缺lessitems
字段名称。 您的查询应阅读
Folder.findOne({_id: Object(5)}, {items: {$elemMatch: {$in: [1,67,9]}}}) .exec(function (err, doc) { });
但是,这仍然不会返回所需的结果,因为正如文档中所述:
$ elemMatch投影将只匹配每个源文档的一个数组元素。
所以你只能得到如下的东西:
{ _id: ObjectId(5), items: [1] }
我没有设置mongoose做这个节点,但你也可以得到你想要的结果在2.2使用新的聚合框架 – 这是一个例子,让你得到你想要的结果。 首先,我的示例文档如下所示:
> db.foo.findOne() { "_id" : ObjectId("50472eb566caf6af6108de02"), "items" : [ 1, 2, 3, 45, 4, 67, 9, 4 ] }
为了达到你想要的,我做了这个:
> db.foo.aggregate( {$match : {"_id": ObjectId("50472eb566caf6af6108de02")}}, {$unwind : "$items"}, {$match : {"items": {$in : [1, 67, 9]}}}, {$group : {_id : "$_id", items : { $push : "$items"}}}, {$project : {_id : 0, items : 1}} ) { "result" : [ { "_id" : ObjectId("50472eb566caf6af6108de02"), "items" : [ 1, 67, 9 ] } ], "ok" : 1 }
为了解释,我将详细地逐行:
{$match : {"_id": ObjectId("50472eb566caf6af6108de02")}}
这是相当明显的 – 它基本上等同于普通查询的查找条件,结果被传递到stream水线中的下一步进行处理。 这是可以使用索引等的一块
{$unwind : "$items"}
这将爆炸数组,创build一个文档stream,每个数组的一个元素。
{$match : {"items": {$in : [1, 67, 9]}}}
这第二场比赛将只返回列表中的文件,基本上将文档stream减less到三个结果集。
{$group : {_id : "$_id", items : { $push : "$items"}}}
我们希望我们的输出是一个数组,所以我们现在必须撤销上面的展开,我们已经select了我们想要的项目,使用_id作为组合键。 注意:如果有多个匹配,这将会有重复的值,如果你想要一个唯一的列表,你将使用$addToSet
而不是$push
{$project : {_id : 1, items : 1}}
最后,这个投影并不是真的需要,但是我把它包括来说明function – 如果你愿意,你可以select不返回_id。
一般$ elemMatch和MongoDB都不会过滤数组中的数据。 $ elemMatch可用于匹配文档,但不会影响要返回的数据。 您只能使用filter参数(find()findOne()调用的第二个参数)包含/排除logging的字段,但不能根据某些查询input过滤结果。