$ elemMatch不适用于新的mongodb 2.2吗?

时间:2012-09-05 05:25:58

标签: node.js mongodb express mongoose

在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]
}

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()调用的第二个参数)来记录/排除文档中的字段,但您无法根据某些查询输入过滤结果。