我在mongodb中有一系列代表过去和即将发生的事件的文档。文档中有两个日期字段,' start'并且'结束'这是bson ISODATE对象。我正在进行查找查询,以获取所有已结束不超过3天的事件。
db.events.find({'end': {'$gte': datetime.utcnow() - timedelta(days=3)})
如何根据今天和事件的结束日期时间之间的时间(和日期)对此查询的响应进行排序。换句话说,2天前结束的事件应该发生在与现在2天后发生的事件大致相同的位置。这很重要,因为我不想先显示已经发生的所有事件,也不想先显示将来发生的事件。
答案 0 :(得分:3)
如果我理解正确,您希望按今天和事件结束日期之间的时间差来排序。因此,如果您明天有一个活动,昨天有一个活动,前一天有一个活动,那么您希望他们进入的活动是:
假设1和2可以互换,具体取决于实际的时差。
这绝对可以通过MongoDB的聚合框架来完成。它的工作原理如下:
timeDelta
)。absTimeDelta
。absTimeDelta
排序。所以看起来应该是这样的:
db.events.aggregate([
{ '$match':
{ 'end':
{ '$gte': datetime.utcnow() - timedelta(days=3) }
}
},
{ '$project':
{
'timeDelta': {
'$subtract': ['$end', datetime.utcnow()]
}
}
},
{ '$project':
{
'absTimeDelta' : {
'$cond' : [
{ '$lte': ['$timeDelta', 0] },
{ '$multiply' : ['$timeDelta', -1 ] },
'$timeDelta'
]
}
}
},
{ '$sort':
{
'absTimeDelta' : 1
}
}
])
编辑:在MongoDB版本3.2中,this JIRA ticket已修复,引入了$abs
operator。这意味着可以删除第二个$project
,并且可以更新第一个'$subtract': ['$end', datetime.utcnow()]
。您可以使用$abs: { '$subtract': ['$end', datetime.utcnow()] }
而不是{{1}}。
答案 1 :(得分:0)
我现在没有看到任何方式可以让MongoDB为您执行此操作mongo does not support, for the moment, sorting using a function。
但是,如果您的范围始终以当天为中心,为什么不每晚更新一个字段,将时间值存储在当天和事件之间?通过这种方式,您可以对其进行索引并对其进行排序。如果您保留多年的数据,您可能只想更新几周的数据,以获得固定时间更新,而不是随着数据增长而增长。