Mongodb 使用组计数获取$group结果
假设我有一个名为“posts”的集合(实际上它是一个更复杂的集合,posts太简单),其结构如下:Mongodb 使用组计数获取$group结果,mongodb,mongodb-query,aggregation-framework,Mongodb,Mongodb Query,Aggregation Framework,假设我有一个名为“posts”的集合(实际上它是一个更复杂的集合,posts太简单),其结构如下: > db.posts.find() { "_id" : ObjectId("50ad8d451d41c8fc58000003"), "title" : "Lorem ipsum", "author" : "John Doe", "content" : "This is the content", "tags" : [ "SOME", "RANDOM", "TAGS" ] } 我预计这个
> db.posts.find()
{ "_id" : ObjectId("50ad8d451d41c8fc58000003"), "title" : "Lorem ipsum", "author" :
"John Doe", "content" : "This is the content", "tags" : [ "SOME", "RANDOM", "TAGS" ] }
我预计这个集合将跨越数十万,也许是数百万,我需要按标签查询帖子,按标签对结果进行分组,并显示分页的结果。这就是聚合框架的用武之地。我计划使用aggregate()方法查询集合:
db.posts.aggregate([
{ "$unwind" : "$tags" },
{ "$group" : {
_id: { tag: "$tags" },
count: { $sum: 1 }
} }
]);
问题是,要创建分页器,我需要知道输出数组的长度。我知道要做到这一点,你可以做到:
db.posts.aggregate([
{ "$unwind" : "$tags" },
{ "$group" : {
_id: { tag: "$tags" },
count: { $sum: 1 }
} }
{ "$group" : {
_id: null,
total: { $sum: 1 }
} }
]);
但这将丢弃先前管道(第一组)的输出。有没有一种方法可以将这两个操作结合起来,同时保留每个管道的输出?我知道整个聚合操作的输出可以用某种语言强制转换为数组,并对内容进行计数,但管道输出可能会超过16Mb的限制。此外,仅为了获得计数而执行相同的查询似乎是一种浪费
那么,是否可以同时获得文档结果和计数?非常感谢您的帮助。除了计算所有标签外,我不确定您是否需要聚合框架,例如:
db.posts.aggregate(
{ "unwind" : "$tags" },
{ "group" : {
_id: { tag: "$tags" },
count: { $sum: 1 }
} }
);
对于每个标记的分页,您可以使用正常的查询语法,如下所示:
db.posts.find({tags: "RANDOM"}).skip(10).limit(10)
$project
将标记和计数保存到tmp
$push
或addToSet
将tmp
存储到数据列表中
{
"result" : [
{
"_id" : null,
"total" : 5,
"data" : [
{
"tag" : "SOME",
"count" : 1
},
{
"tag" : "RANDOM",
"count" : 2
},
{
"tag" : "TAGS1",
"count" : 1
},
{
"tag" : "TAGS",
"count" : 1
},
{
"tag" : "SOME1",
"count" : 1
}
]
}
],
"ok" : 1
}
你真的需要一个完全准确的总数,还是一个近似值?再一次,看起来你在计算所有帖子的数量,所以这不只是一个count()操作吗?我实际上是在对一组帖子进行计数,所以count()不行。完美的解决方案要在聚合管道中保留结果的同时获得总计,我不知道您可以在
$project
管道中的新字段中包含多个字段。这正是我需要的。谢谢。是否可以使用此方法对数据进行$排序、$跳过或$限制?你不能在$project之前限制数据,我也看不到一种不丢失“总数”的方法。另外,{$sort:{'data.count':1}}}似乎不像在非聚合查询中那样正常工作。@Michaeldepterillo,如果我搜索所有带有标记“RANDOM”的帖子,检查一下这个方法是否有效,但我实际上是按帖子的标记对帖子进行分组,结果组就是需要分页的。
{
"result" : [
{
"_id" : null,
"total" : 5,
"data" : [
{
"tag" : "SOME",
"count" : 1
},
{
"tag" : "RANDOM",
"count" : 2
},
{
"tag" : "TAGS1",
"count" : 1
},
{
"tag" : "TAGS",
"count" : 1
},
{
"tag" : "SOME1",
"count" : 1
}
]
}
],
"ok" : 1
}