Javascript 如何使用node.js在mongodb中获得按组名分组的聚合值?

Javascript 如何使用node.js在mongodb中获得按组名分组的聚合值?,javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,我有一个用例,其中我有3个集合。i、 e、模板、组和每个模板的1-动态集合,将在创建模板后立即创建 每个模板由设备组成,每个设备由组集合的组ID组成。动态收集存储模板设备推送的数据 现在,我需要找出Groups集合中按groupName分组的设备的聚合(总和)值 以下是我收集的样本数据 模板数据 { "_id": "5e0ae38729218b0a3861118b", "templateId": "27127206822", "devices": [ { "dev

我有一个用例,其中我有3个集合。i、 e、模板、组和每个模板的1-动态集合,将在创建模板后立即创建

每个
模板
设备
组成,每个
设备
由组集合的
组ID
组成。动态收集存储模板设备推送的数据

现在,我需要找出Groups集合中按groupName分组的设备的聚合(总和)值

以下是我收集的样本数据

模板数据

{
  "_id": "5e0ae38729218b0a3861118b",
  "templateId": "27127206822",
  "devices": [
    {
      "deviceId": "waterTest",
      "_id": "5e0ae49629218b0a3861118f",
      "group": "5e0ae41d29218b0a3861118d",
    },{
       "deviceId": "Test",
       "_id": "5e0af166981f39410cd89b72",
       "group": "5e0af11d981f39410cd89b70"
    }]
}
[
  {
    "_id": "5e0ae793b1384737a4f855cf",
    "template": "27127206822",
    "deviceId": "waterTest",
    "heat" : 20,
    "humidity" : 10
   },{
      "_id": "5e0ae7a2b1384737a4f855d0",
      "template": "27127206822",
      "deviceId": "waterTest",
      "heat" : 40,
      "humidity" : 20
   },{
      "_id": "5e0ae890b1384737a4f855d3",
      "template": "27127206822",
      "deviceId": "waterTest",
      "heat" : 60,
      "humidity" : 50
    },{
       "_id": "5e0af188981f39410cd89b73",
       "template": "27127206822",
       "deviceId": "Test",
       "heat": 60,
       "humidity": 50
   },{
      "_id": "5e0af196981f39410cd89b74",
      "template": "27127206822",
      "deviceId": "Test",
      "heat": 10,
      "humidity": 20
   }]
[{
   "_id": "5e0af11d981f39410cd89b70",
   "template": "5e0ae38729218b0a3861118b",
   "groupName": "Flats"
 },{
    "_id": "5e0ae41d29218b0a3861118d",
    "template": "5e0ae38729218b0a3861118b",
    "groupName": "SPool"
 }]
动态采集数据

{
  "_id": "5e0ae38729218b0a3861118b",
  "templateId": "27127206822",
  "devices": [
    {
      "deviceId": "waterTest",
      "_id": "5e0ae49629218b0a3861118f",
      "group": "5e0ae41d29218b0a3861118d",
    },{
       "deviceId": "Test",
       "_id": "5e0af166981f39410cd89b72",
       "group": "5e0af11d981f39410cd89b70"
    }]
}
[
  {
    "_id": "5e0ae793b1384737a4f855cf",
    "template": "27127206822",
    "deviceId": "waterTest",
    "heat" : 20,
    "humidity" : 10
   },{
      "_id": "5e0ae7a2b1384737a4f855d0",
      "template": "27127206822",
      "deviceId": "waterTest",
      "heat" : 40,
      "humidity" : 20
   },{
      "_id": "5e0ae890b1384737a4f855d3",
      "template": "27127206822",
      "deviceId": "waterTest",
      "heat" : 60,
      "humidity" : 50
    },{
       "_id": "5e0af188981f39410cd89b73",
       "template": "27127206822",
       "deviceId": "Test",
       "heat": 60,
       "humidity": 50
   },{
      "_id": "5e0af196981f39410cd89b74",
      "template": "27127206822",
      "deviceId": "Test",
      "heat": 10,
      "humidity": 20
   }]
[{
   "_id": "5e0af11d981f39410cd89b70",
   "template": "5e0ae38729218b0a3861118b",
   "groupName": "Flats"
 },{
    "_id": "5e0ae41d29218b0a3861118d",
    "template": "5e0ae38729218b0a3861118b",
    "groupName": "SPool"
 }]
集团数据

{
  "_id": "5e0ae38729218b0a3861118b",
  "templateId": "27127206822",
  "devices": [
    {
      "deviceId": "waterTest",
      "_id": "5e0ae49629218b0a3861118f",
      "group": "5e0ae41d29218b0a3861118d",
    },{
       "deviceId": "Test",
       "_id": "5e0af166981f39410cd89b72",
       "group": "5e0af11d981f39410cd89b70"
    }]
}
[
  {
    "_id": "5e0ae793b1384737a4f855cf",
    "template": "27127206822",
    "deviceId": "waterTest",
    "heat" : 20,
    "humidity" : 10
   },{
      "_id": "5e0ae7a2b1384737a4f855d0",
      "template": "27127206822",
      "deviceId": "waterTest",
      "heat" : 40,
      "humidity" : 20
   },{
      "_id": "5e0ae890b1384737a4f855d3",
      "template": "27127206822",
      "deviceId": "waterTest",
      "heat" : 60,
      "humidity" : 50
    },{
       "_id": "5e0af188981f39410cd89b73",
       "template": "27127206822",
       "deviceId": "Test",
       "heat": 60,
       "humidity": 50
   },{
      "_id": "5e0af196981f39410cd89b74",
      "template": "27127206822",
      "deviceId": "Test",
      "heat": 10,
      "humidity": 20
   }]
[{
   "_id": "5e0af11d981f39410cd89b70",
   "template": "5e0ae38729218b0a3861118b",
   "groupName": "Flats"
 },{
    "_id": "5e0ae41d29218b0a3861118d",
    "template": "5e0ae38729218b0a3861118b",
    "groupName": "SPool"
 }]
现在看看我到目前为止编写的聚合查询

let templateId = "27127206822"; // Dynamic Collection

[err, templateData] = await to(mongoose.connection.db.collection(templateId)
  .aggregate([
     {
          $lookup:{
             from:"templates",
             localField:"template",
             foreignField:"templateId",
             as:"template"
          }
      },{ 
          $unwind:"$template"
      },{ 
          $unwind:"$template.devices"
      },{
          $lookup:{
             from:"groups",
             localField:"template.devices.group",
             foreignField:"_id",
             as:"group"
          }
      },{
          $unwind:"$group"
      },{
          $group:{
             _id: "$groupData.groupName",
             heat:{$sum:"$heat"},
             humidity:{$sum:"$humidity"},
             count:{$sum:1}
          }
      }]));
现在,我需要得到组集合的
groupName
分组的每个
设备的
热和湿度的总和。但是我得到了错误的数据。i、 e,一组的总和也被加到所有其他组中

**返回输出**

//Am getting this Data
[
  {
    "_id": "Flats",
    "heat": 190,  // 2 group's data getting added in both the groups
    "humidity": 150,
    "count":5
  },{
    "_id": "SPool",
    "heat": 190,
    "humidity": 150,
    "count":5
  }]
预期产出

[
  {
    "_id": "Flats",
    "heat": 70,
    "humidity": 70,
    "count":2
  },{
    "_id": "SPool",
    "heat": 120,
    "humidity": 80,
    "count":3
  }]
要得到所需的结果,我是否遗漏了什么?

您可以将其添加为下一个聚合阶段,并将其用于计数和相加:

{
    $group: {
        _id: "$group.groupName",
        "count": { $sum: 1 },
        "heat": { $sum: "$heat" },
        "humidity": { $sum: "$humidity" }
    }
}
更新

我解决了这个问题。一旦
$unwind:“$template.devices”
完成,每个文档都会获得
$template.devices
数组中的每个设备,并使用该数组复制文档

因此,为了得到正确的答案,我们需要将
deviceId
与每个文档的template.devices
对象的
deviceId进行匹配

问题是

[err, templateData] = await to(mongoose.connection.db.collection(templateId)
  .aggregate([
     {
          $lookup:{
             from:"templates",
             localField:"template",
             foreignField:"templateId",
             as:"template"
          }
      },{ 
          $unwind:"$template"
      },{ 
          $unwind:"$template.devices"
      },{
          $match:{
            $expr:{
              $eq: [ "$deviceId","$template.devices.deviceId" ]
            }
          }
      },{
          $lookup:{
             from:"groups",
             localField:"template.devices.group",
             foreignField:"_id",
             as:"group"
          }
      },{
          $unwind:"$group"
      },{
          $group:{
             _id: "$groupData.groupName",
             heat:{$sum:"$heat"},
             humidity:{$sum:"$humidity"},
             count:{$sum:1}
          }
      }]));
通过使用它,我们将获得预期的输出。就是

[
  {
    "_id": "Flats",
    "heat": 70,
    "humidity": 70,
    "count":2
  },{
    "_id": "SPool",
    "heat": 120,
    "humidity": 80,
    "count":3
  }]

为什么您要尝试使用外部
模板ID
查找
$lookup
本地
模板
?我看不到任何方法可以在
“13435158964”
和动态集合中的任何值之间进行匹配。我已经使用了它,并且工作正常。但每组都得到了相同的结果。像这样,
[{u id:“游泳池”,“热量”:1498,“湿度”:3924},{{u id:“平坦”,“热量”:1498,“湿度”:3924},{{u id:“游泳池”,“热量”:1498,“湿度”:3924},{“_id”:“公共区域”,“热量”:1498,“湿度”:3924}]
@Aravind他们都引用同一个模板吗?你需要调试你的管道-我首先从
$lookup
开始,看看你是否得到了预期的结果,添加下一个阶段etcYeah,@mickl。他们都引用同一个模板。我想,我发现了问题。实际上,每个组的数据都被添加到了所有组中。但是如何在获取总数时区分组名?@Aravind你能编辑你的问题并展示一个这样的例子吗?@Aravind我猜你是从多个组获取数据,因为你是按
groupName
分组的,更好的方法是用
\u id
替换
groupName
,然后添加
>groupName:{$first:$groupName}
$group
阶段