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

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

文档 数组 items 排序 305    来源:    2025-03-15

在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 数组拆分为多个文档,每个文档包含一个 items 子文档。
  2. $sort: 对拆分的文档按 price 字段进行排序。
  3. $group: 将排序后的子文档重新组合成一个数组。
  4. $project: 可选,用于调整输出格式。

聚合管道代码

db.orders.aggregate([
  // 第一步:拆分 items 数组
  { $unwind: "$items" },

  // 第二步:按 price 字段排序
  { $sort: { "items.price": 1 } },

  // 第三步:重新组合 items 数组
  {
    $group: {
      _id: "$_id",
      order_id: { $first: "$order_id" },
      items: { $push: "$items" }
    }
  },

  // 第四步:可选,调整输出格式
  {
    $project: {
      _id: 1,
      order_id: 1,
      items: 1
    }
  }
])

解释

  1. $unwind: 将 items 数组拆分为多个文档,每个文档包含一个 items 子文档。例如,原始文档会被拆分为三个文档,每个文档包含一个 items 子文档。
  2. $sort: 对拆分的文档按 items.price 字段进行升序排序。
  3. $group: 将排序后的子文档重新组合成一个数组,并保留原始文档的其他字段(如 order_id)。
  4. $project: 可选,用于调整输出格式,确保输出文档的结构与原始文档一致。

输出结果

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

总结

通过使用 $unwind$sort$group 等聚合阶段,你可以轻松地对子文档进行排序。这种方法适用于需要对嵌套数组中的元素进行排序的场景。