我使用mongodb(我在mongodb中新建)存储有关我的耗电量的数据,每分钟都有一条新记录,这是一个例子:
{"id":"5309d4cae4b0fbd904cc00e1","adco":"O","hchc":7267599,"hchp":10805900,"hhphc":"g","ptec":"c","iinst":13,"papp":3010,"imax":58,"optarif":"s","isousc":60,"motdetat":"Á","date":1393156826114}
所以我每天有大约1440条记录。
我想按天计算成本,但问题是我需要当天的最后一条记录,因为这条记录可以给我绝对千瓦时(千瓦时)的数量。因此,如果我删除昨天的最后一个记录的kwh金额,那么我当天的金额为每小时。
字段hchp
给出了这个绝对千瓦时。字段date
对应于度量的时间(以毫秒为单位)。
当天的消费量=当天结束时的绝对消费量 - 昨天结束时的绝对消费量。
如何才能获得mongodb每天的最后一条记录?
注意:我在spring java中使用mongodb,所以我需要这样的查询:
获取所有措施的示例:
@Query("{ 'date' : { $gt : ?0 }}")
public List<Mesure> findByDateGreaterThan(Date date, Sort sort);
答案 0 :(得分:3)
比原来的答案更现代:
db.collection.aggregate([
{ "$sort": { "date": 1 } },
{ "$group": {
"_id": {
"$subtract": ["$date",{"$mod": ["$date",86400000]}]
},
"doc": { "$last": "$$ROOT" }
}},
{ "$replaceRoot": { "newDocument": "$doc" } }
])
同样的原则适用于您实际上$sort
集合,然后$group
所需的分组键从分组边界获取$last
数据。
使事情更清楚,因为原始写作是您可以使用$$ROOT
而不是指定每个文档属性,当然$replaceRoot
阶段允许您完全恢复该数据作为原始文档形式。
但是一般解决方案仍然是$sort
,然后是$group
所需的公共密钥,并保留$last
或$first
,具体取决于排序顺序为所需属性分组边界。
对于BSON日期而不是问题中的时间戳值,请参阅Group result by 15 minutes time interval in MongoDb了解实际使用和返回BSON日期值时如何累积不同时间间隔的不同方法。
不太确定你在这里会发生什么,但如果我的理解是正确的话,你可以总计这样做。所以要获得每天的最后一条记录:
db.collection.aggregate([
// Sort in date order as ascending
{"$sort": { "date": 1 } },
// Date math converts to whole day
{"$project": {
"adco": 1,
"hchc": 1,
"hchp": 1,
"hhphc": 1,
"ptec": 1,
"iinst": 1,
"papp": 1,
"imax": 1,
"optarif": 1,
"isousc": 1,
"motdetat": 1,
"date": 1,
"wholeDay": {"$subtract": ["$date",{"$mod": ["$date",86400000]}]}
}},
// Group on wholeDay ( _id insertion is monotonic )
{"$group":
"_id": "$wholeDay",
"docId": {"$last": "$_id" },
"adco": {"$last": "$adco" },
"hchc": {"$last": "$hchc" },
"hchp": {"$last": "$hchp" },
"hhphc": {"$last": "$hhphc" },
"ptec": {"$last": "$ptec" },
"iinst": {"$last": "$iinst" },
"papp": {"$last": "$papp" },
"imax": {"$last": "$imax" },
"optarif": {"$last": "$optarif",
"isousc": {"$last": "$isouc" },
"motdetat": {"$last": "$motdetat" },
"date": {"$last": "$date" },
}}
])
所以这里的原则是,给定时间戳值,将日期数学表示为每天开始时的午夜时间。然后,由于文档上的_id
键已经是单调的(总是在增加),因此只需将wholeDay
值分组,同时从分组边界中提取$last
文档。
如果您不需要所有字段,则只对您想要的字段进行投影和分组。
是的,你可以在spring数据框架中做到这一点。我确信那里有一个包裹的命令。但除此之外,获得本机命令的咒语是这样的:
mongoOps.getCollection("yourCollection").aggregate( ... )
对于记录,如果您实际上有BSON日期类型而不是时间戳作为数字,那么您可以跳过日期数学:
db.collection.aggregate([
{ "$group": {
"_id": {
"year": { "$year": "$date" },
"month": { "$month": "$date" },
"day": { "$dayOfMonth": "$date" }
},
"hchp": { "$last": "$hchp" }
}}
])