将数组中的第一个项目投射到新字段(MongoDB聚合)

92

我正在使用Mongoose聚合(MongoDB版本3.2)。

我有一个名为users的数组字段。我想要将这个数组中的第一个项目<$project>到一个新的字段user中。

我尝试过:

  { $project: {
    user: '$users[0]',
    otherField: 1
  }},

  { $project: {
    user: '$users.0',
    otherField: 1
  }},

  { $project: {
    user:  $first: '$users'},
    otherField: 1
  }},

但是两种方法都不起作用。

我该如何正确地做呢?谢谢。


可能是在MongoDB中获取数组的第n个元素的重复问题。 - styvane
3个回答

183
更新: 从v4.4版本开始,有一个专门的操作符$first
{ $project: {
    user: { $first: "$users" },
    otherField: 1
}},

这是语法糖。

原始回答:

您可以使用arrayElemAt

{ $project: {
    user: { $arrayElemAt: [ "$users", 0 ] },
    otherField: 1
}},

12
我们如何直接投射数组元素的键?比如 [{ name: 'foo' }],我想直接投射名称。 - Sachin Bhandari
14
@SachinBhandari { $arrayElemAt: [ "$users.key.anotherNestedKey", 0 ] } - Marian Gibala
它返回一个元素 - 但仍然返回一个数组 :( - Saw
@Saw https://www.mongodb.com/docs/manual/reference/operator/aggregation/first-array-element/#behavior 上说应该是项本身。 - Alex Blex
必须执行用户:{ $first: { $first: "$users" } } - 尽管我没有数组的数组。 - Saw
显示剩余2条评论

20
如果它是一个对象数组,并且您想要使用单个对象字段,即:
{
 "users": [
    {name: "John", surname: "Smith"},
    {name: "Elon", surname: "Gates"}
   ]
}

你可以使用:

{ $project: { user: { $first: "$users.name" } } 

编辑(不包括大小写-根据@haytham的评论)

为了从数组中的嵌套文档中排除单个字段,您需要执行两次投影:

 { $project: { user: { $first: "$users" } } 

返回完整的第一个对象,然后排除您不想要的字段,例如:

{ $project: { "user.name" : 0 } 

我们怎样排除匹配?我的意思是如何在此之后传递0? { $project: { user: { $arrayElemAt: [ "$users", 0 ] }, otherField: 1 }}, 或者 { $project: { user: { $first: "$users.name" } } } - haytham
@haytham - 在答案中添加了示例。我认为这不能在单个投影中完成($first + 从第一个结果中排除字段)。 - Michał Szkudlarek

11

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

// { "users": ["Jean", "Paul", "Jack"] }
// { "users": ["Claude"] }
db.collection.aggregate([
  { $project: { user: { $first: "$users" } } }
])
// { "user" : "Jean" }
// { "user" : "Claude" }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接