在聚合中展平MongoDB嵌套数组

在聚合中展平MongoDB嵌套数组,mongodb,aggregation-framework,Mongodb,Aggregation Framework,我有这样的文件: { "many" : {}, "other" : {}, "fields" : {}, "phases" : [ { "type" : 10, "states" : [ { "type" : 10, "time" : ISODate("2018-04-25T13:06:

我有这样的文件:

{
    "many" : {},
    "other" : {},
    "fields" : {},
    "phases" : [ 
        {
            "type" : 10,
            "states" : [ 
                {
                    "type" : 10,
                    "time" : ISODate("2018-04-25T13:06:42.990+02:00")
                }, 
                {
                    "type" : 20,
                    "time" : ISODate("2018-04-25T13:26:12.122+02:00")
                }, 
                {
                    "type" : 30,
                    "time" : ISODate("2018-04-25T13:26:30.124+02:00")
                }
            ]
        }, 
        {
            "type" : 20,
            "states" : [ 
                {
                    "type" : 10,
                    "time" : ISODate("2018-04-25T13:27:58.201+02:00")
                }
            ]
        }
    ]
}
在聚合中,我试图将
状态
展平,包括父级的
类型
,如下所示(所需输出):

我已经完成了附加的
状态
字段,没有使用此聚合的
阶段
字段:

db.docs.aggregate([
{
    $addFields: {
        states: {
            $reduce: {
                  input: "$phases",
                  initialValue: [],
                  in: { $concatArrays: ["$$value", "$$this.states"] }
               }
           }
    }
}
])
“许多其他字段”应该保留,因此我认为分组不是一种选择。
MongoDB版本是3.4


我尝试了很多事情,但都没有结果。我想知道这是否以及如何可能。

您需要使用循环遍历每个数组,然后使用循环遍历到最终的数组

db.state.aggregate(

// Pipeline
[
    // Stage 1
    {
        $unwind: {
            path : "$phases",
            includeArrayIndex : "arrayIndex", // optional
            preserveNullAndEmptyArrays : false // optional
        }
    },

    // Stage 2
    {
        $unwind: {
            path : "$phases.states",
            includeArrayIndex : "arrayIndex", // optional
            preserveNullAndEmptyArrays : false // optional
        }
    },

    // Stage 3
    {
        $project: {
            "phases":"$phases.type",
            "type":"$phases.states.type",
            "time":"$phases.states.time",
        }
    },

    // Stage 4
    {
        $group: {
            "_id":"$_id",
            states: { $push:  { phases: "$phases", type: "$type",time: "$time" } }
        }
    },
]);
db.collection.aggregate([
  { "$addFields": {
    "states": { "$reduce": {
      "input": { "$map": {
        "input": "$phases",
        "as": "pa",
        "in": { "$map": {
          "input": "$$pa.states",
          "as": "st",
          "in": { "type": "$$st.type", "time": "$$st.time", "phase": "$$pa.type" }
        }}
      }},
      "initialValue": [],
      "in": { "$concatArrays": ["$$value", "$$this"] }
    }}
  }}
])

Mohit Kumar Bordia的代码看起来很棒。此外,如果还希望返回旧对象(基于Mohit代码):


您可以使用下面的聚合。用于格式化状态数组以包含相位字段

db.docs.aggregate([
  {"$addFields":{
    "states":{
      "$reduce":{
        "input":"$phases",
        "initialValue":[],
        "in":{
          "$concatArrays":[
            "$$value",
            {"$map":{
              "input":"$$this.states",
              "as":"state",
              "in":{"phase":"$$this.type","type":"$$state.type","time":"$$state.time"}
            }}
          ]
        }
      }
    }
  }}
])
db.getCollection('flatten').aggregate(

// Pipeline
[
    // Stage 1
    {
        $unwind: {
            path : "$phases",
            includeArrayIndex : "arrayIndex", // optional
            preserveNullAndEmptyArrays : false // optional
        }
    },

    // Stage 2
    {
        $unwind: {
            path : "$phases.states",
            includeArrayIndex : "arrayIndex", // optional
            preserveNullAndEmptyArrays : false // optional
        }
    },

    // Stage 3
    {
        $project: {
            "_id" : "$_id",
            "many" : "$many",
            "other" :"$other",
            "fields" : "$fields",
            "phases":"$phases.type",
            "type":"$phases.states.type",
            "time":"$phases.states.time",
        }
    },

    // Stage 4
    {
        $group: {
            "_id":"$_id",
            many : { $first: "$many"},
            other: { "$first": "$other" },
            fields: { "$first": "$fields" },
            states: { $push:  { phases: "$phases", type: "$type",time: "$time" } }
        }
    },
]);
db.docs.aggregate([
  {"$addFields":{
    "states":{
      "$reduce":{
        "input":"$phases",
        "initialValue":[],
        "in":{
          "$concatArrays":[
            "$$value",
            {"$map":{
              "input":"$$this.states",
              "as":"state",
              "in":{"phase":"$$this.type","type":"$$state.type","time":"$$state.time"}
            }}
          ]
        }
      }
    }
  }}
])