获取数组中的第一个元素并使用Aggregate返回? (MongoDB的)

时间:2014-11-05 17:01:15

标签: mongodb mongomapper

如何获取数组中的第一个元素并将其返回到Mongo聚合中?

我尝试在mongo中运行此代码,但失败了:

db.my_collection.aggregate([
    { $project: {
        resp : { my_field: { $slice: 1 } }
    }}
])

OBS :'my_field'是一个有4个位置的数组,我需要它只返回第一个元素。

返回:

uncaught exception: aggregate failed: {
    "errmsg" : "exception: invalid operator '$slice'",
    "code" : 15999,
    "ok" : 0
}

5 个答案:

答案 0 :(得分:12)

从3.2开始,我们可以使用$arrayElemAt来获取数组中的第一个元素

db.my_collection.aggregate([
    { $project: {
        resp : { $arrayElemAt: ['$my_field',0] }
    }}
])

答案 1 :(得分:5)

目前,$slice运算符在聚合管道的$project操作中不可用。 所以你能做的就是,

首先$unwindmy_field数组,然后将它们组合在一起并获取该组的$first元素。

db.my_collection.aggregate([
{$unwind:"$my_field"},
{$group:{"_id":"$_id","resp":{$first:"$my_field"}}},
{$project:{"_id":0,"resp":1}}
])

或使用find()命令,您可以在projection部分使用$ slice运算符。

db.my_collection.find({},{"my_field":{$slice:1}})

更新:根据您的评论,假设您只想要数组中的second项,以获取ID为id的记录。

var field = 2;
var id = ObjectId("...");

然后,下面的聚合命令为您提供my_field_id记录的id数组中的第二项。

db.my_collection.aggregate([
{$match:{"_id":id}},
{$unwind:"$my_field"},
{$skip:field-1},
{$limit:1}
])

上述逻辑无法应用于更多记录,因为它会在$group之后涉及$unwind运算符。 $group运算符为该特定组中的所有记录生成单个记录,使后续阶段中应用的$limit$skip运算符无效。

上面find()查询的一个小变化也会产生预期结果。

db.my_collection.find({},{"my_field":{$slice:[field-1,1]}})

除了这些之外,总有一种方法可以在客户端进行,但如果记录数量非常大,则有点贵:

var field = 2; 
db.my_collection.find().map(function(doc){
return doc.my_field[field-1];
})

从上述选项中选择取决于您的数据大小和应用程序设计。

答案 2 :(得分:1)

根据此票证,$ slice运算符计划在Mongo 3.1.4的$ project操作中可用:https://jira.mongodb.org/browse/SERVER-6074

这会使问题消失。

此版本目前仅为开发人员版本,尚未稳定(截至2015年7月)。期待在10月/ 11月左右的时间。

答案 3 :(得分:0)

Mongo 3.1.6起,

db.my_collection.aggregate([
{ 
    "$project": {
        "newArray" : { "$slice" : [ "$oldarray" , 0, 1 ] }
    }
}
])

其中0是起始索引,1是要切片的元素数

答案 4 :(得分:0)

Mongo 4.4开始,聚合运算符$first可用于访问数组的第一个元素:

// { "my_field": ["A", "B", "C"] }
// { "my_field": ["D"] }
db.my_collection.aggregate([
  { $project: { resp: { $first: "$my_field" } } }
])
// { "resp" : "A" }
// { "resp" : "D" }