如何在MongoDB中的$ match中使用聚合运算符(例如$ year或$ dayOfMonth)? [英] How do I use aggregation operators in a $match in MongoDB (for example $year or $dayOfMonth)?
问题描述
我有一个充满了具有created_date属性的文档的集合。我想通过汇总管道发送这些文档,以对它们进行一些处理。理想情况下,我想先使用$ match过滤它们,然后再对它们进行任何其他处理,以便我可以利用索引,但是我不知道如何在我的新方法中使用新的$ year / $ month / $ dayOfMonth运算符$ match表达式。
I have a collection full of documents with a created_date attribute. I'd like to send these documents through an aggregation pipeline to do some work on them. Ideally I would like to filter them using a $match before I do any other work on them so that I can take advantage of indexes however I can't figure out how to use the new $year/$month/$dayOfMonth operators in my $match expression.
关于如何在$ project操作中使用运算符的例子不胜枚举,但我担心将$ project作为第一步管道,然后我就无法访问索引(MongoDB文档指示第一个表达式必须是$ match才能利用索引)。
There are a few examples floating around of how to use the operators in a $project operation but I'm concerned that by placing a $project as the first step in my pipeline then I've lost access to my indexes (MongoDB documentation indicates that the first expression must be a $match to take advantage of indexes).
样本数据:
{
post_body: 'This is the body of test post 1',
created_date: ISODate('2012-09-29T05:23:41Z')
comments: 48
}
{
post_body: 'This is the body of test post 2',
created_date: ISODate('2012-09-24T12:34:13Z')
comments: 10
}
{
post_body: 'This is the body of test post 3',
created_date: ISODate('2012-08-16T12:34:13Z')
comments: 10
}
我想通过汇总管道运行此操作,以获取对9月份所有帖子的总评论
I'd like to run this through an aggregation pipeline to get the total comments on all posts made in September
{
aggregate: 'posts',
pipeline: [
{$match:
/*Can I use the $year/$month operators here to match Sept 2012?
$year:created_date : 2012,
$month:created_date : 9
*/
/*or does this have to be
created_date :
{$gte:{$date:'2012-09-01T04:00:00Z'},
$lt: {$date:'2012-10-01T04:00:00Z'} }
*/
},
{$group:
{_id: '0',
totalComments:{$sum:'$comments'}
}
}
]
}
此方法有效,但是匹配项无法访问任何索引更复杂的查询:
This works but the match loses access to any indexes for more complicated queries:
{
aggregate: 'posts',
pipeline: [
{$project:
{
month : {$month:'$created_date'},
year : {$year:'$created_date'}
}
},
{$match:
{
month:9,
year: 2012
}
},
{$group:
{_id: '0',
totalComments:{$sum:'$comments'}
}
}
]
}
推荐答案
您已经发现,不能对不在文档中的字段进行$ match(它与find的工作方式完全相同),如果您首先使用$ project,那么您将失去使用的能力索引。
As you already found, you cannot $match on fields that are not in the document (it works exactly the same way that find works) and if you use $project first then you will lose the ability to use indexes.
您可以做的是合并您的努力,如下所示:
What you can do instead is combine your efforts as follows:
{
aggregate: 'posts',
pipeline: [
{$match: {
created_date :
{$gte:{$date:'2012-09-01T04:00:00Z'},
$lt: {date:'2012-10-01T04:00:00Z'}
}}
}
},
{$group:
{_id: '0',
totalComments:{$sum:'$comments'}
}
}
]
}
以上仅提供汇总对于9月份,如果您想汇总多个月,则可以例如:
The above only gives you aggregation for September, if you wanted to aggregate for multiple months, you can for example:
{
aggregate: 'posts',
pipeline: [
{$match: {
created_date :
{ $gte:'2012-07-01T04:00:00Z',
$lt: '2012-10-01T04:00:00Z'
}
},
{$project: {
comments: 1,
new_created: {
"yr" : {"$year" : "$created_date"},
"mo" : {"$month" : "$created_date"}
}
}
},
{$group:
{_id: "$new_created",
totalComments:{$sum:'$comments'}
}
}
]
}
,您会得到一些回报像这样:
and you'll get back something like:
{
"result" : [
{
"_id" : {
"yr" : 2012,
"mo" : 7
},
"totalComments" : 5
},
{
"_id" : {
"yr" : 2012,
"mo" : 8
},
"totalComments" : 19
},
{
"_id" : {
"yr" : 2012,
"mo" : 9
},
"totalComments" : 21
}
],
"ok" : 1
}
这篇关于如何在MongoDB中的$ match中使用聚合运算符(例如$ year或$ dayOfMonth)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!