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

Ale*_*gro 15 mongodb mongomapper

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

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

db.my_collection.aggregate([
    { $project: {
        resp : { my_field: { $slice: 1 } }
    }}
])
Run Code Online (Sandbox Code Playgroud)

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

返回:

uncaught exception: aggregate failed: {
    "errmsg" : "exception: invalid operator '$slice'",
    "code" : 15999,
    "ok" : 0
}
Run Code Online (Sandbox Code Playgroud)

sid*_*ate 14

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

db.my_collection.aggregate([
    { $project: {
        resp : { $arrayElemAt: ['$my_field',0] }
    }}
])
Run Code Online (Sandbox Code Playgroud)


Bat*_*eam 7

目前,$slice运营商$project在聚合管道的操作中不可用.所以你能做的是,

首先$unwind,my_field数组,然后将它们组合在一起并获取$first组的元素.

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

或者使用find()命令,您可以在projection零件中使用$ slice运算符.

db.my_collection.find({},{"my_field":{$slice:1}})
Run Code Online (Sandbox Code Playgroud)

更新:根据您的评论,假设您只想要second数组中的项目,对于具有id的记录id.

var field = 2;
var id = ObjectId("...");
Run Code Online (Sandbox Code Playgroud)

然后,下面的聚合命令为您提供my_field记录数组中的第二项,带有_id,id.

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

上述逻辑不能用于更多的记录,因为它将涉及一个$group运算符$unwind.的$group操作者产生用于所有在该特定组使记录的单个记录$limit$skip在后来的阶段应用运营商是无效的.

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

db.my_collection.find({},{"my_field":{$slice:[field-1,1]}})
Run Code Online (Sandbox Code Playgroud)

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

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

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