我们有一个名为Incident的Collection。其中我们有一个字段StartTime(Date对象类型)。 每天,只要满足事件条件,就会创建新的文档条目并将其插入到集合中。 我们必须得到所有事件,这些事件发生在晚上10点到早上6点之间。 (即从午夜到清晨)。
但是我面临着如何为这个用例编写查询的问题。 由于我们有日期对象,我可以在两个日期之间编写查询到搜索文档。 如何在Date对象上基于时间编写搜索查询。 样本数据:
"StartTime" : ISODate("2015-10-16T18:15:14.211Z")
答案 0 :(得分:1)
这不是一个好主意。但基本上你应用日期聚合运算符:
db.collection.aggregate([
{ "$redact": {
"$cond": {
"if": {
"$or": [
{ "$gte": [{ "$hour": "$StartTime" }, 22] },
{ "$lt": [{ "$hour": "$StartTime" }, 6 ] }
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
使用$redact
仅返回或$$KEEP
符合Date
提取的$hour
和$$PRUNE
或&#的两种条件的文档34;删除"从结果那些没有。
与MongoDB 3.6及其后续版本相比有点短,但实际上并没有什么不同:
db.collection.find({
"$expr": {
"$or": [
{ "$gte": [{ "$hour": "$StartTime" }, 22] },
{ "$lt": [{ "$hour": "$StartTime" }, 6 ] }
]
}
})
总的来说,这不是一个好主意,因为该语句需要扫描整个集合并计算该逻辑条件。
更好的方法是实际存储" "时间"作为一个单独的领域:
var ops = [];
db.collection.find().forEach(doc => {
// Get milliseconds from start of day
let timeMillis = doc.StartTime.valueOf() % (1000 * 60 * 60 * 24);
ops.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": { "$set": { timeMillis } }
}
});
if ( ops.length > 1000 ) {
db.collection.bulkWrite(ops);
ops = [];
}
})
if ( ops.length > 0 ) {
db.collection.bulkWrite(ops);
ops = [];
}
然后你可以简单地查询:
var start = 22 * ( 1000 * 60 * 60 ), // 10PM
end = 6 * ( 1000 * 60 * 60 ); // 6AM
db.collection.find({
"$or": [
{ "timeMillis": { "$gte": start } },
{ "timeMillis": { "$lt": end } }
]
);
该字段实际上可以编入索引,从而快速有效地返回结果。