mongodb单节点等时间间隔(15分钟,1小时等)聚合查询,取每个时间间隔第一条数据,可以查询到全部数据;
查询结果展示出来是每小时第一分钟的数据,即00:00:00,01:00:00,02:00:00,03:00:00…
但是针对mongodb分片副本集,相同的查询语句,只能查到部分数据,应该是没有在全部分片中查找,
查询结果是一个小时内随机时间点的数据,如00:56:00,01:57:00,02:55:00,03:58:00…
sql语句如下
db.getCollection(“test1”).aggregate([
{ $match: { “systime”: { $gte: ‘2022-04-22 00:00:00’, $lt: ‘2022-05-15 00:00:00’ }, “datatype”: “0” } },
{ $group: { “_id”: { “$subtract”: [{ “$subtract”: [ { “$dateFromString”: { ‘dateString’: ‘$systime’ } }, new Date(“1970-01-01”) ] }, {
“$mod”: [{ “$subtract”: [ { “$dateFromString”: { ‘dateString’: ‘$systime’ } }, new Date(“1970-01-01”) ] }, 1000 * 60 *60/*聚合时间段,60分钟*/ ]
} ] },
“systime”: {‘$first’: ‘$systime’},
“有功电能”:{“$first”:”$Transformer_72eaab0e19814f4f81f69a52bad8e40f.ActivePower”},
“有功电能1”:{“$first”:”$Transformer_87361d00db444a419aa0e787e89b46b9.ActivePower”},
}
},
{“$project”: { “_id”: 0 } },
{ $sort: { ‘systime’: 1 } }
],{ allowDiskUse: true })
其实这个跟读取数据顺序有关系,你的sort是针对返回结果集进行排序,而不是对$group聚合数据进行排序,所以读取出来的结果跟实际有出入.
1、在副本集的情况,数据写入单个集合,正常情况下是按照时间顺序写入,读取出来的会按照磁盘上顺序读取或者根据索引顺序读取的。
2、在分片集合下,数据是被打散到不同集合,即在单个集合是有序的,在分片合并时候不一定是有序的。此时需要先排序才能保证first取到第一条数据有序的数据。
非分片表走索引
db.xiaoxu.aggregate([{$match:{systime:{$gte:ISODate(“2022-07-30T00:00:00+0800”),$lt:ISODate(“2022-08-01T00:00:00+0800”)}}},{$group:{“_id”:{$subtract:[{$subtract:[“$systime”,new Date(“1970-01-01”)]},{$mod:[{$subtract:[“$systime”,new Date(“1970-01-01″)]},1000*60*60]}]},systime:{$first:”$systime”}}}])
{ “_id” : NumberLong(“1659196800000”), “systime” : ISODate(“2022-07-30T16:00:01Z”) }
{ “_id” : NumberLong(“1659214800000”), “systime” : ISODate(“2022-07-30T21:00:10Z”) }
{ “_id” : NumberLong(“1659225600000”), “systime” : ISODate(“2022-07-31T00:33:14.791Z”) }
{ “_id” : NumberLong(“1659207600000”), “systime” : ISODate(“2022-07-30T19:00:10Z”) }
{ “_id” : NumberLong(“1659200400000”), “systime” : ISODate(“2022-07-30T17:00:02Z”) }
非分片表不走索引
mongos> db.xiaoxu.aggregate([{$match:{systime:{$gte:ISODate(“2022-07-30T00:00:00+0800”),$lt:ISODate(“2022-08-01T00:00:00+0800”)}}},{$group:{“_id”:{$subtract:[{$subtract:[“$systime”,new Date(“1970-01-01”)]},{$mod:[{$subtract:[“$systime”,new Date(“1970-01-01″)]},1000*60*60]}]},systime:{$first:”$systime”}}},{$sort:{“systime”:1}}])
{ “_id” : NumberLong(“1659196800000”), “systime” : ISODate(“2022-07-30T16:00:01Z”) }
{ “_id” : NumberLong(“1659200400000”), “systime” : ISODate(“2022-07-30T17:00:10Z”) }
{ “_id” : NumberLong(“1659207600000”), “systime” : ISODate(“2022-07-30T19:00:30Z”) }
{ “_id” : NumberLong(“1659214800000”), “systime” : ISODate(“2022-07-30T21:00:10Z”) }
{ “_id” : NumberLong(“1659225600000”), “systime” : ISODate(“2022-07-31T00:33:14.791Z”) }
分片表不走索引
mongos> db.xiaoxu.aggregate([{$match:{systime:{$gte:ISODate(“2022-07-30T00:00:00+0800”),$lt:ISODate(“2022-08-01T00:00:00+0800”)}}},{$group:{“_id”:{$subtract:[{$subtract:[“$systime”,new Date(“1970-01-01”)]},{$mod:[{$subtract:[“$systime”,new Date(“1970-01-01″)]},1000*60*60]}]},systime:{$first:”$systime”}}},{$sort:{“systime”:1}}])
{ “_id” : NumberLong(“1659139200000”), “systime” : ISODate(“2022-07-30T00:33:02.791Z”) }
{ “_id” : NumberLong(“1659196800000”), “systime” : ISODate(“2022-07-30T16:00:01Z”) }
{ “_id” : NumberLong(“1659200400000”), “systime” : ISODate(“2022-07-30T17:00:10Z”) }
{ “_id” : NumberLong(“1659207600000”), “systime” : ISODate(“2022-07-30T19:00:30Z”) }
{ “_id” : NumberLong(“1659214800000”), “systime” : ISODate(“2022-07-30T21:00:10Z”) }
{ “_id” : NumberLong(“1659225600000”), “systime” : ISODate(“2022-07-31T00:33:14.791Z”) }
分片表走索引
mongos> db.xiaoxu.aggregate([{$match:{systime:{$gte:ISODate(“2022-07-30T00:00:00+0800”),$lt:ISODate(“2022-08-01T00:00:00+0800”)}}},{$group:{“_id”:{$subtract:[{$subtract:[“$systime”,new Date(“1970-01-01”)]},{$mod:[{$subtract:[“$systime”,new Date(“1970-01-01″)]},1000*60*60]}]},systime:{$first:”$systime”}}},{$sort:{“systime”:1}}])
{ “_id” : NumberLong(“1659139200000”), “systime” : ISODate(“2022-07-30T00:33:02.791Z”) }
{ “_id” : NumberLong(“1659196800000”), “systime” : ISODate(“2022-07-30T16:00:01Z”) }
{ “_id” : NumberLong(“1659200400000”), “systime” : ISODate(“2022-07-30T17:00:02Z”) }
{ “_id” : NumberLong(“1659207600000”), “systime” : ISODate(“2022-07-30T19:00:10Z”) }
{ “_id” : NumberLong(“1659214800000”), “systime” : ISODate(“2022-07-30T21:00:10Z”) }
{ “_id” : NumberLong(“1659225600000”), “systime” : ISODate(“2022-07-31T00:33:01.791Z”) }
最保险的是在group前面进行排序。
db.xiaoxu.aggregate([{$match:{systime:{$gte:ISODate(“2022-08-01T00:00:00”),$lt:ISODate(“2022-08-03T00:00:00”)}}},{$sort:{systime:1}},{$group:{“_id”:{$subtract:[{$subtract:[“$systime”,new Date(“1970-01-01”)]},{$mod:[{$subtract:[“$systime”,new Date(“1970-01-01″)]},1000*60*60]}]},systime:{$first:”$systime”},name:{$first:”$name”}}},{$sort:{“systime”:1}}])
另外按照小时聚合,可以使用$dateFromString–针对字符串以及$dateToString–转对日期类型。可以不用写这么长代码。
完美解决,感谢大神