MongoDB:通过拆分ID

时间:2018-09-11 15:27:06

标签: mongodb aggregation-framework

我的模式实施受到本教程on official mongo site

的影响
{  
  _id: String,
  data:[
        {
         point_1: Number,
         ts: Date
        }
  ]
}

这基本上是为时间序列数据设计的架构,我将每个设备每小时的数据存储在一个文档中的数组中。我创建了_id字段,该字段结合了发送数据和时间的设备ID。例如,如果具有ID xyz1234的设备在2018-09-11 12:30:00发送数据,则我的_id字段将变为xyz1234:2018091112

如果该设备该小时的文档不存在,我将创建新文档,否则我将数据推送到data数组中。

client.db('iot')
.collection('iotdata')
.update({_id:id},{$push:{data:{point_1,ts:date}}},{upsert:true});

现在我在进行聚合时遇到问题。我正在尝试获取这些类型的值

    通过对设备ID分组,在过去24小时内
  • 许多设备的最低point_1
  • 通过对设备ID进行分组,<24>过去24小时内许多设备的最大point_1
  • 通过按设备ID分组,最近24小时内许多设备的平均point_1

我认为这是一个非常简单的聚合,然后我意识到设备ID不是直接的,而是与时间数据混合在一起的,因此按设备ID分组数据并不是那么直接。如何根据设备ID划分_id和组?我尽力使自己的问题尽可能清楚地写出来,所以如果问题的任何部分不清楚,请在评论中提出问题。

2 个答案:

答案 0 :(得分:1)

您可以从$unwind开始处理数据,以获取每个条目一个文档。然后,您可以使用$substr$indexOfBytes运算符来获得deviceId。然后,您可以应用过滤条件(过去24小时),然后使用$group获取minmaxavg

db.col.aggregate([
    {
        $unwind: "$data"
    },
    {
        $project: {
            point_1: "$data.point_1",
            deviceId: { $substr: [ "$_id", 0, { $indexOfBytes: [ "$_id", ":" ] } ] },
            dateTime: "$data.ts"
        }
    },
    {
        $match: {
            dateTime: { $gte: ISODate("2018-09-10T12:00:00Z") }
        }
    },
    {
        $group: {
            _id: "$deviceId",
            min: { $min: "$point_1" },
            max: { $max: "$point_1" },
            avg: { $avg: "$point_1" }
        }
    }
])

答案 1 :(得分:1)

您可以在3.6中使用以下查询。

db.colname.aggregate([
  {"$project":{
    "deviceandtime":{"$split":["$_id", ":"]},
    "minpoint":{"$min":"$data.point_1"},
    "maxpoint":{"$min":"$data.point_1"},
    "sumpoint":{"$sum":"$data.point_1"},
    "count":{"$size":"$data.point_1"}
  }},
  {"$match":{"$expr":{"$gte":[{"$arrayElemAt":["$deviceandtime",1]},"2018-09-10 00:00:00"]}}},
  {"$group":{
    "_id":{"$arrayElemAt":["$deviceandtime",0]},
    "minpoint":{"$min":"$minpoint"},
    "maxpoint":{"$max":"$maxpoint"},
    "sumpoint":{"$sum":"$sumpoint"},
    "countpoint":{"$sum":"$count"}
  }},
  {"$project":{
    "minpoint":1,
    "maxpoint":1,
    "avgpoint":{"$divide":["$sumpoint","$countpoint"]}
  }}
])