Mongo 数据库聚合管道对嵌套数组对象值进行排序

Mongo DB aggregation pipeline sort on nested array object values

我有 mongo 个具有以下结构的文档:

{
    name: 'AKL to DUD Via CHC',
    rates: [
        {
            container_id: 'abc',
            buyRate: 380
        },
        {
            container_id: 'def',
            buyRate: 410
        }
    ]
}
{
    name: 'AKL to DUD',
    rates: [
        {
            container_id: 'abc',
            buyRate: 400
        },
        {
            container_id: 'def',
            buyRate: 420
        }
    ]
}

我想根据特定 container_idbuyRate 在我的聚合管道中进行排序,例如如果我传入 abccontainer_id 我想对 abcbuyRate 进行排序,以便(在这种情况下)首先返回第二个文档。

我可以通过添加一个由 container_id 筛选比率的字段来使其工作,然后对其进行排序,但它似乎过于复杂:

db.services.aggregate([
    { $addFields: { "containerBuyRate":
            { $filter: {
                input: "$rates",
                as: "rate",
                cond: { $eq: [ "$$rate.container_id", "abc") ] }
            }}
     }},
     { $sort: {'containerBuyRate.buyRate': -1}}
])

有没有更简洁的方法来实现?

要对 containerBuyRate 数组进行排序,您需要将其展开并排序

db.services.aggregate([
     { $addFields: { "containerBuyRate":
        { $filter: {
            input: "$rates",
            as: "rate",
            cond: { $eq: [ "$$rate.container_id", "abc" ] }
        }}
     }},
     { $unwind: "$containerBuyRate" },
     { $sort: {"containerBuyRate.buyRate": -1}},
     { $group: { 
         _id: "$_id",
         containerBuyRate: {$push: "$containerBuyRate"},
         name: { $first: "$name"},
         rates: {$first: "$rates"} 
     }}
])

你的方法很好。

另一种方式:

Difference is $addFields will add one more field as an object.

Working example.

db.getCollection('Example').aggregate([
  { $addFields: {
    containerBuyRate: {$arrayElemAt: [ "$rates", { $indexOfArray: [ "$rates.container_id", "abc" ] } ] }}
  },
  { $sort: {'containerBuyRate.buyRate': -1}}
])

输出:

[
  {
    "_id": ObjectId("5a934e000102030405000002"),
    "containerBuyRate": {
      "buyRate": 405,
      "container_id": "abc"
    },
    "name": "AKL to DUD Via CHC",
    "rates": [
      {
        "buyRate": 405,
        "container_id": "abc"
      },
      {
        "buyRate": 500,
        "container_id": "def"
      }
    ]
  },
  {
    "_id": ObjectId("5a934e000102030405000001"),
    "containerBuyRate": {
      "buyRate": 400,
      "container_id": "abc"
    },
    "name": "AKL to DUD",
    "rates": [
      {
        "buyRate": 400,
        "container_id": "abc"
      },
      {
        "buyRate": 420,
        "container_id": "def"
      }
    ]
  },
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "containerBuyRate": {
      "buyRate": 380,
      "container_id": "abc"
    },
    "name": "AKL to DUD Via CHC",
    "rates": [
      {
        "buyRate": 380,
        "container_id": "abc"
      },
      {
        "buyRate": 410,
        "container_id": "def"
      }
    ]
  },
  {
    "_id": ObjectId("5a934e000102030405000003"),
    "containerBuyRate": {
      "buyRate": 300,
      "container_id": "abc"
    },
    "name": "AKL to DUD Via CHC",
    "rates": [
      {
        "buyRate": 300,
        "container_id": "abc"
      },
      {
        "buyRate": 700,
        "container_id": "def"
      }
    ]
  },
  {
    "_id": ObjectId("5a934e000102030405000004"),
    "containerBuyRate": {
      "buyRate": 100,
      "container_id": "abc"
    },
    "name": "AKL to DUD Via CHC",
    "rates": [
      {
        "buyRate": 1000,
        "container_id": "def"
      },
      {
        "buyRate": 100,
        "container_id": "abc"
      }
    ]
  }
]

谢谢@Alex 指出我在最后一个解决方案中的错误。