MongoDB - 在组后安全地对内部数组进行排序

Ada*_*kis 3 mongodb aggregation-framework

我正在尝试查找与特定条件匹配的所有记录,在本例中_id为特定值,然后仅返回按名称字段排序的前 2 个结果。

这就是我所拥有的

db.getCollection('col1').aggregate([
    {$match: {fk: {$in: [1, 2]}}},
    {$sort: {fk: 1, name: -1}},
    {$group: {_id: "$fk", items: {$push: "$$ROOT"} }},
    {$project: {items: {$slice: ["$items", 2]} }}
])
Run Code Online (Sandbox Code Playgroud)

它有效,但是,不能保证。根据此 Mongo 线程 $group不保证文档顺序。

这也意味着此处和其他地方的所有建议解决方案(建议使用$unwind,然后是$sort,然后$group是 )也不会起作用,原因相同。

使用 Mongo(任何版本)完成此任务的最佳方法是什么?我已经看到可以在$project阶段完成的建议,但我不太确定如何完成。

bur*_*ete 5

您说的结果$group从未排序是正确的。

$group 不对其输出文档进行排序。

因此做一个;

{$sort: {fk: 1}}
Run Code Online (Sandbox Code Playgroud)

然后分组

{$group: {_id: "$fk", ... }}, 
Run Code Online (Sandbox Code Playgroud)

将是白费力气。


但有一线希望与分拣前$group阶段与name: -1。由于您使用的是$push(不是$addToSet),因此插入的对象将保留它们在结果中新创建的items数组中的顺序$group。您可以在此处查看此行为(管道的副本)

items数组将始终具有;

"items": [
  {
    ..
    "name": "Michael"
  },
  {
    ..
    "name": "George"
  }
]
Run Code Online (Sandbox Code Playgroud)

以相同的顺序,因此您的嵌套数组排序不是问题!虽然我无法在文档中找到确切的报价来确认这种行为,但您可以检查;

  • 或者是确认的地方。
  • 另外,蓄电池运营商名单$group,其中$addToSet"Order of the array elements is undefined."其描述,而类似的运营商$push不提供,这可能是一种间接的证据?:)

只是对您的管道进行简单的修改,您可以将fk: 1排序从前$group阶段移到后$group阶段;

db.getCollection('col1').aggregate([
    {$match: {fk: {$in: [1, 2]}}},
    {$sort: {name: -1}},
    {$group: {_id: "$fk", items: {$push: "$$ROOT"} }},
    {$sort: {_id: 1}},
    {$project: {items: {$slice: ["$items", 2]} }}
])
Run Code Online (Sandbox Code Playgroud)

应该足以使主要结果数组顺序也固定。在mongoplayground查看