【问题标题】:MongoDB $reduce(aggregation) group with the sum of the nested document in arrays and count by groupMongoDB $reduce(aggregation) 组与数组中嵌套文档的总和并按组计数
【发布时间】:2020-01-13 06:30:07
【问题描述】:

MongoDB 聚合框架查询:$group、$project、$addFields 和 $reduce。

用例: 我在集合中有多个带有嵌套文档数组的文档,需要一个结果分组依据和每个分组项的总和作为累积量。此外,在年份(日期)上具有匹配参数,如果年份匹配,则只有该年份文档应分组,并且返回卷的总和(嵌套文档数组)。

以下是集合中的文档:

{
    "_id": "1",
    "LSD": {
        "name": "TDL 05",
        "LSDNumber": "031"
    },
    "POD": [{           
            "Volume": 35.40,
            "VolUnit": "m3"
        },
        {           
            "Volume": 20.75,
            "VolUnit": "m3"
        },
        {
            "Volume": 15,
            "VolUnit": "m3"
        }
    ],
     "createdon": {
        "$date": "2014-08-02T18:49:17.000Z"
    }
},
{
    "_id": "2",
    "LSD": {
        "name": "Stock Watering",
        "LSDNumber": "01"
    },

    "POD": [{
            "Volume": 105,
            "VolUnit": "m3"
        },
        {
            "Volume": 70,
            "VolUnit": "m3"
        },
        {
            "Volume": 35,
            "VolUnit": "m3"
        }
    ],
     "createdon": {
        "$date": "2014-08-02T18:49:17.000Z"
    }
},
{
    "_id": "3",
    "LSD": {
        "name": "TDL 30 Stock Water",
        "LSDNumber": "030"
    },

    "POD": [{
        "Volume": 87,
        "VolUnit": "m3"
    }],
     "createdon": {
        "$date": "2019-08-02T18:49:17.000Z"
    }
},
{
    "_id": "4",
    "LSD": {
        "name": "TDL 30 Stock Water",
        "LSDNumber": "030"
    },
    "POD": [{
        "Volume": 25.12,
        "VolUnit": "m3"
    }],
     "createdon": {
        "$date": "2019-08-02T18:49:17.000Z"
    }
},
{
    "_id": "5",
    "LSD": {
        "name": "TDL 05",
        "LSDNumber": "031"
    },
    "POD": [
        {
            "Volume": 21,
            "VolUnit": "m3"
        }
    ],
     "createdon": {
        "$date": "2014-08-02T18:49:17.000Z"
    }
}

我有一个查询(C# Driver 2.0),按“LSD.LSDNumber”和“POD.Volume”的总和分组。此处未添加匹配参数。这很好用。

查询:

{
    aggregate([{
        "$group": {
            "_id": "$LSD.LSDNumber",            
            "doc": {
                "$push": "$POD"
            },
            "data": {
                "$first": "$$ROOT"
            }
        }
    }, {
        "$addFields": {
            "LSDNumber": "$_id",            
            "GroupByDocCount": {
                "$size": "$doc"
            },
            "Cumulative": {
                "$reduce": {
                    "input": "$doc",
                    "initialValue": [],
                    "in": {
                        "$concatArrays": ["$$value", "$$this"]
                    }
                }
            }
        }
    }, {
        "$project": {
            "LSDNumber": 1,
            "GroupByDocCount": 1,           
            "CumulativeVol": {
                "$sum": "$Cumulative.Volume"
            }
        }
    }])
}

下面是结果。

{    
    "LSDNumber":"031",
    "GroupByDocCount": 2,
    "CumulativeVol": 92.15
},
{    
    "LSDNumber":"030",
    "GroupByDocCount": 2,
    "CumulativeVol": 112.12
},
{    
    "LSDNumber":"01",
    "GroupByDocCount": 1,
    "CumulativeVol": 210
}

但是,我想按年份(在“createdon”)日期以及按(LSD.LSDNumber)和总和(POD.Volume)分组来获取文档匹配。 例如,如果年份是 2014 年,那么下面的结果应该是。

{    
    "LSDNumber":"031",
    "GroupByDocCount": 2,
    "CumulativeVol": 92.15,
    "Year": 2014
},
{    
    "LSDNumber":"01",
    "GroupByDocCount": 1,
    "CumulativeVol": 210,
    "Year": 2014
}

我尝试的查询总是什么都不返回。

{
    aggregate([{
        "$project": {
            "LSDNumber": 1,
            "GroupByDocCount": 1,
            "CumulativeVol": {
                "$sum": "$Cumulative.Volume"
            },
            "year": {
                "$year": "$data.createdon"
            }
        }
    }, {
        "$match": {
            "year": 2014
        }
    }, {
        "$group": {
            "_id": "$LSD.LSDNumber",
            "year": {
                "$first": "$year"
            },
            "doc": {
                "$push": "$POD"
            },
            "data": {
                "$first": "$$ROOT"
            }
        }
    }, {
        "$addFields": {
            "LSDNumber": "$_id",
            "yearCreate": "$year",
            "GroupByDocCount": {
                "$size": "$doc"
            },
            "Cumulative": {
                "$reduce": {
                    "input": "$doc",
                    "initialValue": [],
                    "in": {
                        "$concatArrays": ["$$value", "$$this"]
                    }
                }
            }
        }
    }])
}

这里出了什么问题。任何帮助将不胜感激!

【问题讨论】:

  • 为什么项目中"$year": "$data.createdon"中有$data?应该只是$createdon
  • @DaveStSomeWhere 抱歉回复晚了。无论如何,用$data.createdon 更正了$createdon,但结果相同。

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

您可以在 $addField 管道中添加 Year 变量,然后添加 $match

{
    "$group": {
        "_id": "$LSD.LSDNumber",            
        "doc": {
            "$push": "$POD"
        },
        "data": {
            "$first": "$$ROOT"
        }
    }
}, {
    "$addFields": {
        "LSDNumber": "$_id",            
        "GroupByDocCount": {
            "$size": "$doc"
        },
        "Cumulative": {
            "$reduce": {
                "input": "$doc",
                "initialValue": [],
                "in": {
                    "$concatArrays": ["$$value", "$$this"]
                }
            }
        },
        "Year": {
            "$year": "$data.createdon"
        }
    }
}, {
    "$match" : {"Year" : 2014}
}, {
    "$project": {
        "LSDNumber": 1,
        "GroupByDocCount": 1,           
        "CumulativeVol": {
            "$sum": "$Cumulative.Volume"
        },
        "Year" : "$Year"
    }
}

=== 结果 ===

/* 1 */
{
    "_id" : "01",
    "LSDNumber" : "01",
    "GroupByDocCount" : 1,
    "CumulativeVol" : 210,
    "Year" : 2014
}

/* 2 */
{
    "_id" : "031",
    "LSDNumber" : "031",
    "GroupByDocCount" : 2,
    "CumulativeVol" : 92.15,
    "Year" : 2014
}

【讨论】:

    【解决方案2】:

    有点晚了,但这是我的答案。我们只需要在最后阶段向管道添加一个项目阶段(额外)。但是,@Valijon 的回答符合同样的要求。

    {
        aggregate([{
            "$project": {
                "LSDNumber": "$LSD.LSDNumber",
                "year": {
                    "$year": "$createdon"
                },
                "PointOfDiversionVolumeDetails": 1
            }
        }, {
            "$match": {
                "year": 2014
            }
        }, {
            "$group": {
                "_id": "$LSDNumber",
                "doc": {
                    "$push": "$PointOfDiversionVolumeDetails"
                }
            }
        }, {
            "$addFields": {
                "GroupByDocCount": {
                    "$size": "$doc"
                },
                "Cumulative": {
                    "$reduce": {
                        "input": "$doc",
                        "initialValue": [],
                        "in": {
                            "$concatArrays": ["$$value", "$$this"]
                        }
                    }
                }
            }
        }, {
            "$project": {
                "CumulativeVol": {
                    "$sum": "$Cumulative.Volume"
                },
                "LSDNumber": 1,
                "GroupByDocCount": 1
            }
        }, {
            "$sort": {
                "GroupByDocCount": -1
            }
        }])
    }
    

    【讨论】:

      猜你喜欢
      • 2020-07-01
      • 2020-11-17
      • 2023-03-05
      • 2012-09-27
      • 2019-03-24
      • 1970-01-01
      • 1970-01-01
      • 2020-11-09
      • 2017-03-03
      相关资源
      最近更新 更多