是否可以在Aggregation Frameworks mongo中按投影顺序获取字段

svs*_*eja 8 mongodb mongodb-query aggregation-framework

我有以下文件:

{ "_id" : 3, "quizzes" : [ 4, 5, 5 ], "labs" : [ 6, 5 ], "final" : 78, "midterm" : 70 }
{ "_id" : 1, "quizzes" : [ 4, 5, 5 ], "labs" : [ 6, 5 ], "midterm" : 70 }
Run Code Online (Sandbox Code Playgroud)

如果我运行以下查询:

   db.students.aggregate([  { "$project": {  "midterm": 1,"final": 1   } } ])
Run Code Online (Sandbox Code Playgroud)

结果如下:

{ "_id" : 3, "final" : 78, "midterm" : 70 }
{ "_id" : 1, "midterm" : 70 }
Run Code Online (Sandbox Code Playgroud)

如果我仍然在shell中更改投影中的顺序,则字段的顺序是相同的?我们可以根据查询的顺序重新获得订单吗?

db.students.aggregate([  { "$project": { "final":1, "midterm": 1  } } ])
{ "_id" : 3, "final" : 78, "midterm" : 70 }
{ "_id" : 1, "midterm" : 70 }
Run Code Online (Sandbox Code Playgroud)

用例为什么订单很重要:

我有一个集合存储用户的日常数据.如果用户在那天做了一些活动,那个用户的文档中会有一个字段.我们将这一天存储200天......在另一个集合中,我们必须更新何时是过去200天内的userFirstActive ...

注意:在用户没有执行任何活动的那天,该密钥不会有任何条目...

因此,如果我们进行200天的投影...除了id之外的第一个条目将是第一个活跃的日子.是否可以在不获取整个文档的情况下实现此目的并检查密钥是否存在?

Sal*_*eem 18

MongoDB默认按插入顺序返回字段.

例如

db.students.aggregate([  { "$project": {  "midterm": 1,"final": 1   } } ])
Run Code Online (Sandbox Code Playgroud)

将返回

{ "_id" : 3, "final" : 78, "midterm" : 70 }
{ "_id" : 2, "midterm" : 60, "final" : 55 }
{ "_id" : 1, "midterm" : 70 }
Run Code Online (Sandbox Code Playgroud)

你可以看到第二条记录,它的字段按我们插入的顺序排列.但是,我们可以通过重命名字段来按顺序获取它们.

例如

db.students.aggregate([  { "$project": {  _midterm:"$midterm","_final": "$final"}}])
Run Code Online (Sandbox Code Playgroud)

以上查询将返回

{ "_id" : 3, "_midterm" : 70, "_final" : 78 }
{ "_id" : 2, "_midterm" : 60, "_final" : 55 }
{ "_id" : 1, "_midterm" : 70 }
Run Code Online (Sandbox Code Playgroud)

中期是第一次,最后是第二次,只有一个例外.字段名称以_.为前缀.如果你想要原始名字,你可以project再次.

db.students.aggregate(
[
{ "$project": {  _midterm:"$midterm","_final": "$final"}},
{ "$project": {  midterm:"$_midterm","final": "$_final"}}
])
Run Code Online (Sandbox Code Playgroud)

它会回来的

{ "_id" : 3, "midterm" : 70, "final" : 78 }
{ "_id" : 2, "midterm" : 60, "final" : 55 }
{ "_id" : 1, "midterm" : 70 }
Run Code Online (Sandbox Code Playgroud)

  • 实际原因并非完全是“插入顺序”,而是字段在上一个流水线阶段所处的顺序实际上是正确的,因为像$ project和$ group这样的操作有效地“复制”了位置和/或内容作为“优化” ”技术。因此,您是对的,确保不同顺序的唯一方法是使用“临时”名称或有效地使用不同的名称。只是在这种情况下,该提案并不是最有效的方法。 (2认同)

小智 8

在聚合数组的最后一个值中,添加此属性

  {
    $replaceRoot: {
      newRoot: {
        field_1: '$field_1',
        field_2: '$field_2',
        ...
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)