查找每天的最后一条记录

elo*_*one 6 mongodb mongodb-query aggregation-framework

我使用 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}
Run Code Online (Sandbox Code Playgroud)

所以我每天大约有 1440 条记录。

我想按天计算成本,但问题是我需要当天的最后一个记录,因为这个记录可以给我绝对千瓦时(千瓦时)的数量。因此,如果我删除昨天最后一个记录的千瓦时量,我就有了当天的千瓦时量。

该领域hchp给了我这个绝对的千瓦时。该字段date对应于以毫秒为单位的度量时间。

当天消费=当天末绝对消费-昨天末绝对消费。

如何在 mongodb 中获得每天的最后一条记录?

注意:我在 spring java 中使用 mongodb,所以我需要这样的查询:

获取所有度量的示例:

@Query("{ 'date' : { $gt : ?0 }}")
public List<Mesure> findByDateGreaterThan(Date date, Sort sort);
Run Code Online (Sandbox Code Playgroud)

Nei*_*unn 6

比原始答案更现代:

db.collection.aggregate([
  { "$sort": { "date": 1 } },
  { "$group": {
    "_id": {
      "$subtract": ["$date",{"$mod": ["$date",86400000]}]
    },
    "doc": { "$last": "$$ROOT" }
  }},
  { "$replaceRoot": { "newDocument": "$doc" } }
])
Run Code Online (Sandbox Code Playgroud)

相同的原则适用于您本质上$sort是集合,然后$group在所需的分组键上$last从分组边界拾取数据。

使事情更清楚一点,因为原始写作是您可以使用$$ROOT而不是指定每个文档属性,当然$replaceRoot阶段允许您将该数据完全恢复为原始文档形式。

但是一般的解决方案仍然是$sort首先,然后$group是所需的公共键,并根据所需属性的分组边界的排序顺序保持$last$first

同样对于 BSON 日期而不是问题中的时间戳值,请参阅在 MongoDb 中按 15 分钟时间间隔对结果进行分组,了解有关如何在实际使用和返回 BSON 日期值的不同时间间隔内累积的不同方法。


不太确定您在这里要做什么,但如果我的理解是正确的,您可以汇总执行此操作。因此,要获取每天的最后一条记录:

db.collection.aggregate([
  { "$sort": { "date": 1 } },
  { "$group": {
    "_id": {
      "$subtract": ["$date",{"$mod": ["$date",86400000]}]
    },
    "doc": { "$last": "$$ROOT" }
  }},
  { "$replaceRoot": { "newDocument": "$doc" } }
])
Run Code Online (Sandbox Code Playgroud)

所以这里的原则是,给定时间戳值,进行日期数学运算,将其投影为每天开始时的午夜时间。然后因为_id文档上的键已经是单调的(总是增加),然后简单地对wholeDay值进行$last分组,同时从分组边界拉出文档。

如果您不需要所有字段,则只需对您想要的字段进行投影和分组。

是的,您可以在 spring 数据框架中执行此操作。我确定那里有一个包装的命令。但除此之外,获得本机命令的咒语是这样的:

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" },
    }}
])
Run Code Online (Sandbox Code Playgroud)

作为记录,如果您实际上有 BSON 日期类型而不是时间戳作为数字,那么您可以跳过日期数学:

mongoOps.getCollection("yourCollection").aggregate( ... )
Run Code Online (Sandbox Code Playgroud)