简体   繁体   English

具有多个匹配或并集的Mongo聚合

[英]Mongo aggregations with multiple match or union

I am trying to aggregate some information coming from different devices. 我正在尝试汇总来自不同设备的一些信息。 Given a set of device ids, I'd like to count the number of times values occur. 给定一组设备ID,我想计算值出现的次数。 The bit that I am struggling with is we only want to work on each device's last report. 我苦苦挣扎的一点是,我们只想处理每个设备的最新报告。

For example, 4 devices have stored hundreds of thousands of reports in the report collection. 例如,有4台设备已在报告集中存储了数十万个报告。 The reports tells us if there was a networkDown event or not (boolean). 这些报告告诉我们是否存在networkDown事件(布尔值)。 I want to count the number of times networkDown is true or false within the 4 device's last reports. 我想计算4个设备的上次报告中networkDown为true或false的次数。

I am using mongoDB 2.4.4 我正在使用mongoDB 2.4.4

A report looks similar to this: 报告看起来类似于此:

{
  "_id":ObjectId("52571500fa1fc70437000001"),
  "device_id" : ObjectId("51f14f9f9809c4404f00000a"),
  "payload":{
    "name":"Status",
    "properties":{
      "property":{
        "deviceIdentifier":"My Device",
        "networkDown":"false"
      }
    }
  },
  "updated_at":ISODate("2013-10-10T20:58:40.674Z"),
  "created_at":ISODate("2013-10-10T20:58:40.674Z")
}

The group I can do on all records for all 4 devices. 我可以在所有4个设备的所有记录上执行的组。 Say, 说,

  db.report.aggregate(
  [
    { $match: { device_id: 
        {
          $in:         
          [
            ObjectId("51f14f9f9809c4404f00000a"),
            ObjectId("523ab68a9809c4e490000059"),
            ObjectId("522f37b89809c4e8cf000033"),
            ObjectId("522f38019809c4ae070000d3")        
          ]
        }
      }
    },    
    { $group: { _id: "$payload.properties.property.networkDown", total: { $sum: 1 } } }                     
  ])


{
    "result" : [
        {
            "_id" : "true",
            "total" : 2
        },
        {
            "_id" : "false",
            "total" : 278539
        }
    ],
    "ok" : 1
}

But how can I limit the query to only work on the last report for each device? 但是,如何限制查询仅在每个设备的最后一个报告上起作用?

Thanks for looking! 感谢您的光临!

You will have first sort on the basis of {updated_at:1} .Then group by device_id and use the $last operator to take only the last networkDown field since the documents are sorted . 您将首先基于{updated_at:1}排序。然后按device_id进行分组,并使用$ last运算符仅采用最后一个networkDown字段,因为对文档进行了排序。 Then do another group on the networkDown property. 然后在networkDown属性上执行另一个组。 I know its a little complicated , but here's the query: 我知道它有点复杂,但这是查询:

db.reports.aggregate(
[
 { $match: { device_id: 
        {
          $in:         
          [
            ObjectId("51f14f9f9809c4404f00000a"),
            ObjectId("523ab68a9809c4e490000059"),
            ObjectId("522f37b89809c4e8cf000033"),
            ObjectId("522f38019809c4ae070000d3")        
          ]
        }
      }
    },
    {$sort:{updated_at:1}},
    {$group:
       {_id:"$device_id",
        networkDown:{$last:"$payload.properties.property.networkDown"}
       }
    },
    {$group:{_id:"$networkDown",count:{$sum:1}}}
])

I haven't tried it properly , but it should work.Let me know in case of any propblem 我没有正确尝试过,但是应该可以。如果有任何问题,请通知我

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM