我有一个集合,总结了与其他集合中的文档相关的一些数据。它的结构大致如下:
{
campaignId : ObjectId(...)
impressions : {
...
'2016-09-20': 1800,
'2016-09-21': 1500,
'2016-09-22': 2000
},
clicks : {
...
'2016-09-20': 60,
'2016-09-21': 55,
'2016-09-22': 80
}
}
我意识到有更好的方法可以做到,但这是我无法控制的。
问题是我需要查询过去7天内有展示次数的文档。
所以我需要根据字段键而不是值进行查询。
是否可以在查询中执行此操作?
答案 0 :(得分:1)
由于您需要根据字段键而不是您需要为之前N天(在您的情况下为7天)提供密钥的值进行查询。 在构建这些键(以编程方式或手动方式)之后,您可以通过不同的方式实现这一点-----
1 - 使用$where
db.collectionName.find({$where: function() {
var previous2days = ["2016-09-21","2016-09-20"]
for (var field in this.impressions) {
if(previous2days.indexOf(field) > -1) return true;
}
return false;
}})
2。使用$exists
db.getCollection('Test').find({
"$or":
[
{ "impressions.2016-09-21" : { "$exists": true } },
{ "impressions.2016-09-20" : { "$exists": true } }
//add more conditional objects to consider data for more previous dates
]
})
以编程方式构建此类查询(在此示例中使用JavaScript构建查询)
var previous2days = ["2016-09-21","2016-09-20"]
var query = { "$or" : [] }
for(var key in previous2days) {
var q = {}
q["impressions."+previous2days[key]] = { "$exists" : true }
query.$or.push(q)
}
console.log(JSON.stringify(query))
这将为您提供所需格式的最终查询
{"$or":[{"impressions.2016-09-21":{"$exists":true}},{"impressions.2016-09-20":{"$exists":true}}]}
答案 1 :(得分:0)
有趣。
我认为你必须使用带有七个日期的$ exists作为参数动态创建或查询,我认为没有任何有效的方法可以通过像lte或gte这样的条件查询字段。
db.campaign.find({$or : [{impressions.2016-09-21 : {$exists : true}},{impressions.2016-09-20 : {$exists : true}},{impressions.2016-09-19 : {$exists : true}}....]})
我知道您无法对查询中的日期进行硬编码,因为过去7天是动态的,但您可以轻松地使用函数创建动态查询字符串,然后将其用于查询。
另一种方式(我可能不会工作,但值得一试)是在查询中的$ where,$ where接受一个函数,你可以尝试操作函数来实现所需的,这将是凌乱但你所有必须要做的是使用'this'作为文档,如果文档验证你的条件则返回true,否则返回false。
总而言之,没有简单的办法解决这个问题。