【问题标题】:MongoDB - filter documents to one per dayMongoDB - 每天过滤一个文档
【发布时间】:2017-02-27 03:02:05
【问题描述】:

我有一系列事件。在我的应用程序中,这些事件每天多次添加到事件集合中。每个事件都有一个 eventName 属性,它是一个字符串。每个事件还有一个包含一些数据点的数据对象。其中一些数据点全天变化,但有一个保持不变。我想要整天保持不变的数据。 我想编写一个 mongo 查询来获取 eventName 开启的事件,但我每天只想要一个。

我的收藏:

/* 1 */
{
    "_id" : ObjectId("5789449365109ca974906921"),
    "eventDate" : ISODate("2016-07-15T20:16:18.508Z"),
    "eventName": "turnOff",
    "data" : {
        "sameAllDay" : 2000,
        "variesAllDay1" : 1234,
        "variesAllDay2" : 2345,
    }
}

/* 2 */
{
    "_id" : ObjectId("5789449365109ca974906921"),
    "eventDate" : ISODate("2016-07-15T20:16:13.592Z"),
    "eventName": "turnOn",
    "data" : {
        "sameAllDay" : 2000,
        "variesAllDay1" : 1235,
        "variesAllDay2" : 2346,
    }
}

/* 3 */
{
    "_id" : ObjectId("5789449365109ca974906921"),
    "eventDate" : ISODate("2016-07-15T20:16:03.507Z"),
    "eventName": "turnOff",
    "data" : {
        "sameAllDay" : 2000,
        "variesAllDay1" : 1236,
        "variesAllDay2" : 2347,
    }
}

/* 4 */
{
    "_id" : ObjectId("5789449365109ca974906921"),
    "eventDate" : ISODate("2016-07-15T20:15:58.592Z"),
    "eventName": "turnOn",
    "data" : {
        "sameAllDay" : 2000,
        "variesAllDay1" : 1237,
        "variesAllDay2" : 2348,
    }
}

/* 5 */
{
    "_id" : ObjectId("5789449365109ca974906921"),
    "eventDate" : ISODate("2016-07-16T20:15:48.507Z"),
    "eventName": "turnOn",
    "data" : {
        "sameAllDay" : 3000,
        "variesAllDay1" : 1238,
        "variesAllDay2" : 2349,
    }
}

/* 6 */
{
    "_id" : ObjectId("5789449365109ca974906921"),
    "eventDate" : ISODate("2016-07-16T20:16:18.508Z"),
    "eventName": "turnOn",
    "data" : {
        "sameAllDay" : 3000,
        "variesAllDay1" : 1209,
        "variesAllDay2" : 9876,
    }
}

我想要什么:

/* 2 */
{
    "_id" : ObjectId("5789449365109ca974906921"),
    "eventDate" : ISODate("2016-07-15T20:16:13.592Z"),
    "eventName": "turnOn",
    "data" : {
        "sameAllDay" : 2000,
        "variesAllDay1" : 1235,
        "variesAllDay2" : 2346,
    }
}

/* 5 */
{
    "_id" : ObjectId("5789449365109ca974906921"),
    "eventDate" : ISODate("2016-07-16T20:15:48.507Z"),
    "eventName": "turnOn",
    "data" : {
        "sameAllDay" : 3000,
        "variesAllDay1" : 1238,
        "variesAllDay2" : 2349,
    }
}

这是我目前的查询:

db.getCollection('event').aggregate([
  {$match: { 'eventName': 'turnOn' }}, 
  {$sort: { 'eventDate': -1 } }
  //filter to one event per day
])

如何获得一组开启事件,其中集合中的每个事件都有唯一的一天?一天中的时间无关紧要。月份和年份很重要。

【问题讨论】:

  • 您想要每天的最后一个事件turnOn 还是每天的第一个事件turnOn?根据您的要求,对于2016-07-15,这是当天的最后一个turnOn,对于2016-07-16,这是当天的第一个turnOn
  • 我不在乎这是一天的第一天还是一天的最后一天。它们每个都包含一个名为“sameAllDay”的数据点,这对于给定日期的每个事件都是相同的。

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

你可以这样做:

  • 2 $project(附加一个用于连接年-月-日)
  • 1 $match
  • 1 $group
  • 1 $sort

mongo 查询是:

db.event.aggregate([{
  $project: {
    _id: 1,
    eventName: 1,
    data: 1,
    day: {
      "$dayOfMonth": "$eventDate"
    },
    month: {
      "$month": "$eventDate"
    },
    year: {
      "$year": "$eventDate"
    }
  }
}, {
  $project: {
    _id: 1,
    eventName: 1,
    data: 1,
    eventDate: {
      $concat: [{
          $substr: ["$year", 0, 4]
        },
        "-", {
          $substr: ["$month", 0, 2]
        },
        "-", {
          $substr: ["$day", 0, 2]
        }
      ]
    }
  }
}, {
  $match: {
    "eventName": "turnOn"
  }
}, {
  $group: {
    _id: "$eventDate",
    eventDate: {
      $first: "$eventDate"
    },
    data: {
      $first: '$data'
    }
  }
}, {
  $sort: {
    eventDate: 1
  }
}])

它将执行以下操作:

  • 第一个$project:与日期分开的年/月/日
  • 第二个$project:连接日期
  • $match你的eventName
  • $group 按创建日期年月日只有第一个日期和第一个数据
  • $sort日期

输出给你:

{
  "_id": "2016-7-15",
  "eventDate": "2016-7-15",
  "data": {
    "sameAllDay": 2000,
    "variesAllDay1": 1235,
    "variesAllDay2": 2346
  }
} {
  "_id": "2016-7-16",
  "eventDate": "2016-7-16",
  "data": {
    "sameAllDay": 3000,
    "variesAllDay1": 1238,
    "variesAllDay2": 2349
  }
}

【讨论】:

  • 感谢您的回答。查询运行但结果为空。如果我在没有 $group 的情况下尝试查询,我会得到一个结果。 _id: "$eventDate" 有什么作用?
  • 这意味着它按日期分组,精确地按之前使用投影生成的值“YYYY-MM-DD”。我的值与您在问题中所写的值完全相同,请尝试在您的控制台中执行这些值:gist.github.com/akinaru/895639fb19c133a6a47fb6b83b8a8aa1
  • 我现在开始工作了。您的最新链接很有帮助。非常感谢!
猜你喜欢
  • 2015-07-23
  • 1970-01-01
  • 1970-01-01
  • 2015-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-19
  • 2014-09-11
相关资源
最近更新 更多