繁体   English   中英

如何按多个字段对子文档数组进行分组?

[英]How to group an array of subdocuments by multiple fields?

我花了一天的大部分时间在这上面,现在没有想法了。 这是我的收藏:

[
  {
    "_id": "ID_XXX",
    "logs": [
      {
        "lead_id": 123,
        "list_id": "list_44",
        "order_id": "order_1"
      },
      {
        "lead_id": 124,
        "list_id": "list_44",
        "order_id": "order_2"
      }
    ]
  },
  {
    "_id": "ID_YYY",
    "logs": [
      {
        "lead_id": 125,
        "list_id": "list_44",
        "order_id": "order_2"
      },
      {
        "lead_id": 126,
        "list_id": "list_44",
        "order_id": "order_2"
      },
      {
        "lead_id": 127,
        "list_id": "list_44",
        "order_id": "order_3"
      },
      {
        "lead_id": 128,
        "list_id": "list_66",
        "order_id": "order_3"
      }
    ]
  }
]

我只是想获取list_idorder_id的计数,同时保留它们所在文档的_id 。这是我想要的 output:

[
  {
    "_id": "ID_XXX",
    "counts": [
      {
        "lists": {"list_44": 2},
      },
      {
        "orders": {"order_1": 1, "order_2": 1}
      }
    ]
  },
  {
    "_id": "ID_YYY",
    "counts": [
      {
        "lists": {"list_44": 3, "list_66": 1},
      },
      {
        "orders": {"order_2": 2, "order_3": 2}
      }
    ]
  }
]

我尝试了太多的聚合变体,无法在此处列出,但最新的是:

db.collection.aggregate([
  {
    $unwind: "$logs"
  },
  {
    $group: {
      _id: "$_id",
      lists: {
        $push: "$logs.list_id"
      },
      orders: {
        $push: "$logs.order_id"
      }
    }
  }
])

这并没有给我想要的东西。 谁能指出我正确的方向? 这是操场链接: https://mongoplayground.net/p/f-jk7lbSrJ0

  • $reduce迭代logs循环,使用$objectToArray objectToArray 将logs object 转换为 k(key) v(value) 格式的数组, $concatArrays使用$reduce reduce 中的 initialValue,
  • 上面的$filter将结果减少为输入并从logs中过滤所需字段
  • $unwind解构logs数组
db.collection.aggregate([
  {
    $addFields: {
      logs: {
        $filter: {
          input: {
            $reduce: {
              input: "$logs",
              initialValue: [],
              in: { $concatArrays: ["$$value", { $objectToArray: "$$this" }] }
            }
          },
          cond: { $in: ["$$this.k", ["list_id", "order_id"]] }
        }
      }
    }
  },
  { $unwind: "$logs" },
  • $group by _idlogs object 并使用$sum获取总数
  {
    $group: {
      _id: {
        _id: "$_id",
        logs: "$logs"
      },
      counts: { $sum: 1 }
    }
  },
  • $group by _id如果logs.klist_id则创建lists数组,否则返回 k 和 v 格式$$REMOVE ,与订单相同,在order_id的基础上创建orders数组
  • $addFieldslists数组从 k 和 v 格式转换为 object 格式,与订单数组and same as for
  {
    $group: {
      _id: "$_id._id",
      lists: {
        $push: {
          $cond: [
            { $eq: ["$_id.logs.k", "list_id"] },
            {
              k: "$_id.logs.v",
              v: "$counts"
            },
            "$$REMOVE"
          ]
        }
      },
      orders: {
        $push: {
          $cond: [
            { $eq: ["$_id.logs.k", "order_id"] },
            {
              k: "$_id.logs.v",
              v: "$counts"
            },
            "$$REMOVE"
          ]
        }
      }
    }
  },
  {
    $addFields: {
      lists: { $arrayToObject: "$lists" },
      orders: { $arrayToObject: "$orders" }
    }
  }
])

操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM