首页 > 解决方案 > MongoDB - 在组后安全地对内部数组进行排序

问题描述

我正在尝试查找与某个条件匹配的所有记录,在这种情况下_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]} }}
])

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

这也意味着这里和其他地方的所有建议的解决方案,建议使用$unwind,后跟$sort,然后$group,出于同样的原因,也将不起作用。

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

标签: mongodbaggregation-framework

解决方案


你说的结果$group永远不会排序是正确的。

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

因此做一个;

{$sort: {fk: 1}}

然后分组

{$group: {_id: "$fk", ... }}, 

将是白费力气。


但是,在舞台前进行排序也有一线希望。由于您使用的是(而不是),因此插入的对象将保留它们在结果中新创建的数组中的顺序。您可以在此处查看此行为(您的管道副本)$groupname: -1$push$addToSetitems$group

items数组将始终具有;

"items": [
  {
    ..
    "name": "Michael"
  },
  {
    ..
    "name": "George"
  }
]

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

  • 这个
  • 或者是确认的地方。
  • 此外,累加器运算符列表对于$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]} }}
])

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


推荐阅读