【发布时间】:2015-08-27 04:29:55
【问题描述】:
问题:
我有一个包含不同类型事件的集合。一个事件的日期可能会改变,我们想知道它是什么时候改变的以及它从什么地方改变的,所以当前日期存储在一个包含所有以前事件的数组中。
[
{
_id: ...,
eventDates : [
{ created: ISODate(...), eventDate: ISODate(...) },
{ created: ISODate(...), eventDate: ISODate(...) }
],
eventType: ...,
otherData: ....
}
]
所以基本上,每个对象都有一个类型和一个日期列表,其中最后创建的 eventDate 才是最重要的。
对于每个 eventType,我想列出相对于给定日期的上一个和下一个事件。
一个例子:
所以给出以下数据:
[ {
_id: 1,
eventType: "sports",
eventDates: [
//first scheduled to 1st of February...
{ created: ISODate(2015-01-01), eventDate: ISODate(2015-02-01) },
//...but later rescheduled to 10th of February.
{ created: ISODate(2015-01-02), eventDate: ISODate(2015-02-10) }
],
otherData: ...
},
{
_id: 2,
eventType: "sports",
eventDates: [
//Scheduled to 5st of February...
{ created: ISODate(2015-01-10), eventDate: ISODate(2015-02-05) }
],
otherData: ...
},
{
_id: 3,
eventType: "sports",
eventDates: [
//Scheduled to 1st of March...
{ created: ISODate(2015-01-20), eventDate: ISODate(2015-03-01) }
//...but later rescheduled to 20th of February.
{ created: ISODate(2015-01-30), eventDate: ISODate(2015-02-20) }
],
otherData: ...
}
]
我预计 2015 年 2 月 15 日的输出如下:
[ {
eventType: "sports",
previousEvent: {
_id: 1,
eventType: "sports",
eventDates: [
{ created: ISODate(2015-01-01), eventDate: ISODate(2015-02-01) },
{ created: ISODate(2015-01-02), eventDate: ISODate(2015-02-10) }
],
otherData: ...
},
nextEvent: {
_id: 3,
eventType: "sports",
eventDates: [
{ created: ISODate(2015-01-20), eventDate: ISODate(2015-03-01) }
{ created: ISODate(2015-01-30), eventDate: ISODate(2015-02-20) }
],
otherData: ...
}
}
对于 2015 年 3 月 1 日的日期,我会像以前一样拥有第三个事件,而下一个事件将为空(不再安排更多事件)。 类似地,对于日期 2015-02-01,我会将第二个事件作为下一个事件,而前一个事件将为空(没有过去的事件)。
我的尝试
第一步是找到活动的当前日期。为此,我将首先$unwind 所有日期,以便稍后选择最新的:
db.getCollection("Events").aggregate([
{$unewind: "$eventDates" }
])
=> { result: [
{ _id: ...., eventDates: { created: ISODate(...), eventDate: ISODate(...) }, otherData: ...},
{ _id: ...., eventDates: { created: ISODate(...), eventDate: ISODate(...) }, otherData: ...},
{ _id: ...., eventDates: { created: ISODate(...), eventDate: ISODate(...) }, otherData: ...}
], ok: 1 }
接下来,我会尝试把$group和$max的所有旧的eventDates都扔掉
db.getCollection("Events").aggregate([
{$unwind: "$eventDates" },
{$group: { _id: "$_id", eventDate: { $max: "$eventDates.created" }}
])
=> { result: [
{ _id: ...., eventDate: ISODate(...) },
{ _id: ...., eventDate: ISODate(...) }
], ok: 1 }
但是现在,我只有每个事件的 id 以及最后一次设置事件日期的时间。我没有事件日期本身,也没有其他事件数据。
如何告诉$group-step 从具有最高@eventDates.created-value 的文档中返回所有内容?
第二步将$project eventDate 放入一个新的“过去是”字段。我猜这很简单。
db.getCollection("Events").aggregate([
{$unwind: "$eventDates" },
{$project: { event: "$$ROOT", inThePast: {$lt: ["$eventDate.eventDate", new Date()]}}},
{$group: { _id: "$_id", eventDate: { $max: "$eventDates.created" }}
])
第三步是新的挑战。对于每个 eventType,我想要日期最高的过去事件,以及最低日期的未来事件....
我想最终得到的是一个类似于这个的结构:
{ result: [
{ eventType: ....,
previous: { _id: ...., eventDate: ISODate(...), otherData: ...},
next: { _id: ...., eventDate: ISODate(...), otherDate: ....}
}
], ok: 1 }
我在这方面完全正确吗?
【问题讨论】:
-
所以“简而言之”,如果我说得对的话。您想使用输入日期(或当前日期)进行测试并找到在该日期之前和之后“立即”发生的事件?或者只是组中最小和最大的?真正好的问题会给出样本数据和预期的结果。它既清晰又给我们一些可玩的东西:)
-
不得不说这实际上可能是一个“规范问题”,即如何从给定的匹配点找到“上一个”和“下一个”项目,如果只是措辞比它更好,并且带有清晰的样品和结果。自上次结果以来,我一直在研究这个一个多小时。但就目前而言,除非可以编辑该问题,否则这个问题(以及我认为我现在接近的答案)将逐渐消失。
-
今晚晚些时候我会花一些时间来解决这个问题,以使事情更清楚。就像制定问题并向样本添加实际时间戳一样。够了吗?
-
好吧,看看您是否可以将它与现在给出的答案相匹配,因为这应该可以解决问题。我至少冒昧地选择了一个更合适的标题。而且我猜你至少应该为一个真正难以解决的问题投赞成票。
-
我试图更好地表述它并添加了一些示例数据以更清楚地说明我要解决的问题。
标签: mongodb mongodb-query aggregation-framework