{
"_id" : ObjectId("5852725660632d916c8b9a38"),
"response_log" : [
{
"campaignId" : "AA",
"created_at" : ISODate("2016-12-20T11:53:55.727Z")
},
{
"campaignId" : "AB",
"created_at" : ISODate("2016-12-20T11:55:55.727Z")
}]
}
我有一个包含数组的文档。我想选择所有从当前时间过去2小时内没有response_log.created_at的文档,并且过去24天的response_log.created_at计数少于3。
我不知道该怎么做。请帮忙
最佳答案
您可以使用聚合框架来过滤文档。具有 $match
和 $redact
步骤的管道将进行过滤。
考虑运行以下聚合操作,其中 $redact
允许您使用 $cond
运算符处理逻辑条件,并使用系统变量 $$KEEP
来“保留”逻辑条件为true或 ojit_re条件为假的文件。
此操作类似于使用 $$PRUNE
管道,该管道选择集合中的字段,并创建一个新字段来保存逻辑条件查询的结果,然后再保存后续的 $project
,不同之处在于 $match
使用单个管道阶段效率更高:var moment = require('moment'),
last2hours = moment().subtract(2, 'hours').toDate(),
last24hours = moment().subtract(24, 'hours').toDate();
MongoClient.connect(config.database)
.then(function(db) {
return db.collection('MyCollection')
})
.then(function (collection) {
return collection.aggregate([
{ '$match': { 'response_log.created_at': { '$gt': last2hours } } },
{
'$redact': {
'$cond': [
{
'$lt': [
{
'$size': {
'$filter': {
'input': '$response_log',
'as': 'res',
'cond': {
'$lt': [
'$$res.created_at',
last24hours
]
}
}
}
},
3
]
},
'$$KEEP',
'$$PRUNE'
]
}
}
]).toArray();
})
.then(function(docs) {
console.log(docs)
})
.catch(function(err) {
throw err;
});
解释说明
在上面的聚合操作中,如果执行第一个 $redact
管道步骤collection.aggregate([
{ '$match': { 'response_log.created_at': { '$gt': last2hours } } }
])
返回的文档将是从当前时间开始的最近2个小时内没有$match
的文档,其中使用 "response_log.created_at"
API通过momentjs库创建了last2hours
变量。
然后,前面带有 subtract
的管道将通过使用 $redact
三元运算符对上面的文档进行进一步过滤,该三元运算符对该逻辑表达式进行求值,该逻辑表达式使用 $cond
来获取计数,并通过 ojit_r将带有已过滤数组的元素返回到ojit_r符合其他逻辑条件{
'$lt': [
{
'$size': {
'$filter': {
'input': '$response_log',
'as': 'res',
'cond': { '$lt': ['$$res.created_at', last24hours] }
}
}
},
3
]
}
如果此条件为true,则将其转换为 $size
,或者将 $filter
“删除”为评估条件为假的文档。
关于node.js - 在MongoDB中汇总后查找,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43605730/