【问题标题】:How to get aggregated total and split of total sum which is also sum of items in mongoDB如何获得总和的汇总和拆分,这也是mongoDB中的项目总和
【发布时间】:2018-02-26 21:18:46
【问题描述】:

我有类似如下的mongo文档:

{"client" : "ashwini",
    "data" : [ 
        {
            .....

            "ac" : [ 
                {
                    "cord" : [ 
                        5.0, 
                        0.0
                    ],
                    "power" : 10.0,on:true
                }, 
                {
                    "cord" : [ 
                        52.0, 
                        0.0
                    ],
                    "power" : 22.0,on:true
                }, 
                {
                    "cord" : [ 
                        85.0, 
                        0.0
                    ],
                    "power" : 50.0,on:false
                }, 
                {
                    "cord" : [ 
                        5.0, 
                        50.0
                    ],
                    "power" : 30.0,on:true
                }
            ],
            "fan" : [ 
                {
                    "cord" : [ 
                        10.0, 
                        20.0
                    ],
                    "power" : 50.0,on:true
                }, 
                {
                    "cord" : [ 
                        60.0, 
                        20.0
                    ],
                    "power" : 10.0,on:true
                }, 
                {
                    "cord" : [ 
                        85.0, 
                        20.0
                    ],
                    "power" : 40.0,on:false
                }, 
                {
                    "cord" : [ 
                        10.0, 
                        70.0
                    ],
                    "power" : 10.0,on:true
                }
            ],
            "light" : [ 
                {
                    "cord" : [ 
                        30.0, 
                        0.0
                    ],
                    "power" : 34.0,on:true
                }, 
                {
                    "cord" : [ 
                        66.0, 
                        0.0
                    ],
                    "power" : 10.0,on:true
                }, 
                {
                    "cord" : [ 
                        82.0, 
                        90.0
                    ],
                    "power" : 69.0,on:true
                }, 
                {
                    "cord" : [ 
                        20.0, 
                        50.0
                    ],
                    "power" : 70.0,on:true
                }
            ],
            "name" : "Palm Meadows",
            "floor" : -1.0
        }, 
        ......
    ]
 }

我希望查询的输出如下:

 {
        agr:{
          lights:10,
          ac:10,
          fan:20
        },
        split:[
          {
            name:"Palm Meadows",
            power:40,
            location:"Mahadevpura",
            lights:10,
            ac:10,
            fan:20
          },
       ....
       ],
}

其中第一个 agr 是客户端“ashwini”的灯光/交流/风扇字段中所有功率的总和,该客户端“ashwini”已打开并拆分具有按名称和位置唯一的灯光/交流/风扇的单独总和

我的第一次试验如下

db.getCollection('property').aggregate([
                    {$match:{"client":"ashwini"}},
                    {
                        $group:{
                            _id:"$_id",
                            values:{
                                $addToSet:{
                                    name:"$data.name",
                                    floor:"$data.floor",
                                    location:"$data.location",
                                    lights:{$sum:"$data.lights.power"},
                                    fan:{$sum:"$data.fan.power"},
                                    ac:{$sum:"$data.ac.power"}
                                    }
                            }
                        }
                    }
                ])

输出如下

我不确定如何达到我的要求

【问题讨论】:

    标签: mongodb mongoose mongodb-query aggregation-framework


    【解决方案1】:

    您可以在 3.4 中使用以下聚合。

    第一部分是计算每个位置的总和值。

    第二部分是汇总所有位置的总和值。

    对于每个 ($map) data 行,$filter 数据文档,其中on 字段为真,然后$sum为每个请求字段(内部$let)设置power 值。

    外部$let 表达式计算每个元素的power 值,该值是请求字段与聚合请求字段值的总和,namelocation 作为split 阶段内的split 字段.

    将所有位置的所有请求字段值聚合为$addFields 阶段内的aggr 字段,该阶段也保留现有值。

    db.getCollection('property').aggregate([
      {"$match":{"client":"ashwini"}},
      {"$project":{
        "_id":0,
        "split":{
          "$map":{
            "input":"$data",
            "as":"d",
            "in":{
              "$let":{
                "vars":{
                  "ac":{
                    "$sum":{
                      "$let":{
                        "vars":{"acm":{"$filter":{"input":"$$d.ac","as":"ac","cond":"$$ac.on"}}},
                        "in":"$$acm.power"
                      }
                    }
                  },
                  "fan":{
                    "$sum":{
                      "$let":{
                        "vars":{"fanm":{"$filter":{"input":"$$d.fan","as":"fan","cond":"$$fan.on"}}},
                        "in":"$$fanm.power"
                      }
                    }
                  },
                  "light":{
                    "$sum":{
                      "$let":{
                        "vars":{"lightm":{"$filter":{"input":"$$d.light","as":"light","cond":"$$light.on"}}},
                        "in":"$$lightm.power"
                      }
                    }
                  }
                },
                "in":{
                  "name":"$$d.name",
                  "location":"$$d.location",
                  "power":{"$sum":["$$ac","$$fan","$$light"]},
                  "ac":"$$ac",
                  "fan":"$$fan",
                  "light":"$$light"
                }
              }
            }
          }
        }
      }},
      {"$addFields":{
        "aggr":{
          "ac":{"$sum":"$split.ac"},
          "fan":{"$sum":"$split.fan"},
          "light":{"$sum":"$split.light"},
          "power":{"$sum":"split.power"}
        }
      }}
    ])
    

    使用以下查询输出位置和名称的计算值。

    $unwind 数据数组后跟 $group 位置和名称。

    $reduce 遍历分组数据以求和所有请求的字段值。

    $group 通过 _id 将数据值推送到数组中,以计算所有位置的值。

    db.getCollection('property').aggregate([
      {"$unwind":"$data"},
      {"$group":{"_id":{"id":"$_id","name":"$data.name", "location":"$data.location"},"data":{"$push":"$data"}}},
      {"$project":{
        "values":{
          "$reduce":{
            "input":"$data",
            "initialValue":{
                  "power":0,
                  "ac":0,
                  "fan":0,
                  "light":0
                },
            "in":{
              "$let":{
                "vars":{
                  "ac":{
                    "$sum":{
                      "$let":{
                        "vars":{"acm":{"$filter":{"input":"$$this.ac","as":"ac","cond":"$$ac.on"}}},
                        "in":"$$acm.power"
                      }
                    }
                  },
                  "fan":{
                    "$sum":{
                      "$let":{
                        "vars":{"fanm":{"$filter":{"input":"$$this.fan","as":"fan","cond":"$$fan.on"}}},
                        "in":"$$fanm.power"
                      }
                    }
                  },
                  "light":{
                    "$sum":{
                      "$let":{
                        "vars":{"lightm":{"$filter":{"input":"$$this.light","as":"light","cond":"$$light.on"}}},
                        "in":"$$lightm.power"
                      }
                    }
                  }
                },
                "in":{
                  "power":{"$add":["$$value.power", {"$sum":["$$ac","$$fan","$$light"]}]},
                  "ac":{"$add":["$$value.ac", "$$ac"]},
                  "fan":{"$add":["$$value.fan", "$$fan"]},
                  "light":{"$add":["$$value.light", "$$light"]}
                }
              }
            }
          }
        }
      }},
      {"$group":{"_id":"$_id.id", "split":{"$push":{"name":"$_id.name","location":"$_id.location","values":"$values"}}}},
      {"$addFields":{
        "aggr":{
          "ac":{"$sum":"$split.values.ac"},
          "fan":{"$sum":"$split.values.fan"},
          "light":{"$sum":"$split.values.light"},
          "power":{"$sum":"split.values.power"}
        }
      }}
    ])
    

    【讨论】:

    • 谢谢,它在名称和位置对重复的地方给出了错误的拆分,并且在“$data”和“power”的值中出现了尽可能多的项目:405.0,“ac”:112.0,“fan " : 110.0,"light" : 183.0 总是与这些相同。
    • Yw。我假设数据包含每个位置的值。您可以在帖子中添加竞争文档吗?当前文档不完整,就像没有位置字段一样。
    • 为我工作。您有按楼层分隔的位置。因此,您可以将 floor 添加到名称和位置,这将帮助您区分查询,例如外部 $let 中的 "name":"$$d.name", "location":"$$d.location","floor":"$$d.floor"
    • 很公平。我会更新答案。给我一些时间。
    猜你喜欢
    • 2013-06-07
    • 2014-07-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 2014-01-23
    • 1970-01-01
    • 2011-12-05
    • 2018-12-12
    相关资源
    最近更新 更多