插件窝 干货文章 如何使用MongoDB聚合管道对子文档进行排序?

如何使用MongoDB聚合管道对子文档进行排序?

文档 数组 items 排序 819    来源:    2025-03-13

在MongoDB中,聚合管道(Aggregation Pipeline)是一个非常强大的工具,可以用于对数据进行复杂的处理和转换。如果你需要对子文档进行排序,可以使用 $unwind$sort$group 等聚合阶段来实现。

假设你有一个集合 orders,每个文档包含一个 items 数组,数组中的每个元素是一个子文档,表示订单中的商品。你想要对每个订单中的商品按价格进行排序。

示例数据

{
  "_id": 1,
  "order_id": "ORD123",
  "items": [
    { "product": "A", "price": 20 },
    { "product": "B", "price": 10 },
    { "product": "C", "price": 30 }
  ]
}

目标

items 数组中的子文档按 price 字段进行升序排序。

聚合管道步骤

  1. $unwind: 将 items 数组展开,使每个子文档成为一个独立的文档。
  2. $sort: 对展开后的文档按 price 字段进行排序。
  3. $group: 将排序后的子文档重新组合回原来的数组。
  4. $project: 可选,用于调整输出文档的结构。

聚合管道代码

db.orders.aggregate([
  // 展开 items 数组
  { $unwind: "$items" },

  // 按 price 字段进行排序
  { $sort: { "items.price": 1 } },

  // 重新组合回原来的数组
  {
    $group: {
      _id: "$_id",
      order_id: { $first: "$order_id" },
      items: { $push: "$items" }
    }
  },

  // 可选:调整输出文档的结构
  {
    $project: {
      _id: 1,
      order_id: 1,
      items: 1
    }
  }
])

解释

  1. $unwind: 将 items 数组展开,每个子文档成为一个独立的文档。例如,展开后会有三个文档,每个文档包含一个 items 子文档。
  2. $sort: 对展开后的文档按 items.price 字段进行升序排序(1 表示升序,-1 表示降序)。
  3. $group: 将排序后的子文档重新组合回原来的数组。$push 操作符用于将子文档重新推入 items 数组。
  4. $project: 可选,用于调整输出文档的结构。在这个例子中,我们保留了所有字段。

输出结果

{
  "_id": 1,
  "order_id": "ORD123",
  "items": [
    { "product": "B", "price": 10 },
    { "product": "A", "price": 20 },
    { "product": "C", "price": 30 }
  ]
}

总结

通过使用 $unwind$sort$group 等聚合阶段,你可以轻松地对子文档进行排序。这种方法不仅适用于简单的排序,还可以扩展到更复杂的聚合操作中。