Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何按多个字段对子文档数组进行分组?_Arrays_Mongodb_Aggregation Framework_Aggregate - Fatal编程技术网

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

Arrays 如何按多个字段对子文档数组进行分组?,arrays,mongodb,aggregation-framework,aggregate,Arrays,Mongodb,Aggregation Framework,Aggregate,我已经花了一天的大部分时间在这上面,现在已经没有主意了。这是我的收藏: [ { "_id": "ID_XXX", "logs": [ { "lead_id": 123, "list_id": "list_44", "order_id": "order_1"

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

[
  {
    "_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\u id
order\u id
的计数,同时保留它们所在文档的
\u id
。这是我想要的输出:

[
  {
    "_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"
      }
    }
  }
])
这并没有给我想要的。谁能给我指出正确的方向吗?这里是操场链接:

  • $reduce
    要迭代
    日志的循环
    ,请使用
    $objectToArray
    $concatarray
    $reduce
    中的初始值,将
    日志
    对象转换为k(键)v(值)格式的数组
  • 上面的
    $filter
    将结果减少为输入,并从
    日志中筛选所需字段
  • $unwind
    解构
    日志
    数组
  • $group
    \u id
    记录对象并使用
    $sum
  • $group
    \u id
    分组,如果
    记录,则生成
    列表
    数组。k
    列表id
    并以k和v格式返回,否则返回
    $$REMOVE
    ,与
    订单
    相同,基于
    订单id
    生成订单数组
  • $addFields
    使用$arrayToObject
    列表
    数组从k和v格式转换为对象格式,与
    订单`数组相同

这很有效,谢谢。但是考虑到这种聚合的相对复杂性,您是否建议我将原始数据拉入代码中,并在JS中执行此操作,而不是聚合它?我只是想知道你认为什么更有效。这只是一个逻辑,你可以用你的客户端语言来做,它比查询更有效,如果你真的想在聚合中做,那么试试操作符,你可以在这个函数中做JS代码。明白了。在客户端执行此操作时,我担心这些日志可能包含数十万条条目,而且由于我的数据库与我的节点应用程序不在同一台服务器上,我不想将所有数据下载到我的应用程序中来处理它。无论哪种方式,都要感谢你的洞察力。
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: {
      _id: {
        _id: "$_id",
        logs: "$logs"
      },
      counts: { $sum: 1 }
    }
  },
  {
    $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" }
    }
  }
])