在MongoDB的新版本中,我们可以使用$ elemMatch投影运算符来限制查询对数组的单个匹配元素的响应。 http://docs.mongodb.org/manual/reference/projection/elemMatch/
但似乎在mongoose 3中还没有用,这里是例子:
{
_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]
}
答案 0 :(得分:4)
这里的mongodb文档具有误导性,我们会更新它们。
它的说法是你现在可以在你的投影中使用$ elemMatch,即你的领域选择:
https://gist.github.com/3640687
另请参阅:https://github.com/learnboost/mongoose/issues/1085
发送文档的[编辑]提取请求:https://github.com/mongodb/docs/pull/185
答案 1 :(得分:2)
首先,您在$ elemMatch运算符前面缺少items
字段名称。您的查询应该是
Folder.findOne({_id: Object(5)}, {items: {$elemMatch: {$in: [1,67,9]}}})
.exec(function (err, doc) { });
但是这仍然不会返回所需的结果,因为正如文档中所述:
$ elemMatch投影仅匹配每个源的一个数组元素 文档。
所以你只会得到类似的东西:
{
_id: ObjectId(5),
items: [1]
}
答案 2 :(得分:1)
我没有让mongoose设置为使用node执行此操作,但您也可以使用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")}}
这是相当明显的 - 它基本上等同于常规查询的查找条件,结果将传递到要处理的管道中的下一步。这是可以使用索引等的部分。
{$unwind : "$items"}
这会爆炸数组,创建一个文档流,一个用于数组的每个元素。
{$match : {"items": {$in : [1, 67, 9]}}}
第二次匹配将仅返回列表中的文档,基本上将文档流减少到三个结果集。
{$group : {_id : "$_id", items : { $push : "$items"}}}
我们希望我们的输出是一个数组,所以我们必须撤消上面的展开,因为我们选择了我们想要的项目,使用_id作为分组的关键。注意:如果有多个匹配,则会有重复值,如果您想要使用$addToSet
代替$push
的唯一列表
{$project : {_id : 1, items : 1}}
然后最后,这个投影并不是真的需要,但是我把它包括在内以说明功能 - 如果你愿意,可以选择不返回_id。
答案 3 :(得分:-1)
$ elemMatch和MongoDB一般都不会过滤数组中的数据。 $ elemMatch可用于匹配文档,但不会影响要返回的数据。您只能使用filter参数(find()findOne()调用的第二个参数)来记录/排除文档中的字段,但您无法根据某些查询输入过滤结果。