【问题标题】:Obtaining $group result with group count使用组数获取 $group 结果
【发布时间】:2012-11-11 19:59:15
【问题描述】:

假设我有一个名为“posts”的集合(实际上它是一个更复杂的集合,posts 太简单了),结构如下:

> 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 限制。此外,执行相同的查询只是为了获得计数似乎是一种浪费。

那么可以同时获取文档结果和计数吗?任何帮助表示赞赏。

【问题讨论】:

  • 您真的需要一个完全准确的总数,还是需要一个近似值?话又说回来,看起来您正在计算所有帖子,所以这不只是您可以执行的 count() 操作吗?
  • 我实际上是在对一组帖子进行计数,所以 count() 不会这样做。
  • 完美的解决方案是获取总数的同时将结果保存在聚合管道stackoverflow.com/a/39784851/3666966

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

除了计算所有标签之外,我不确定您是否需要聚合框架,例如:

db.posts.aggregate(
  { "unwind" : "$tags" },
  { "group" : {
      _id: { tag: "$tags" },
      count: { $sum: 1 }
  } }
);

对于每个标签的分页,您可以使用普通的查询语法 - 如下所示:

db.posts.find({tags: "RANDOM"}).skip(10).limit(10)

【讨论】:

  • 如果我要搜索所有带有“RANDOM”标签的帖子,那会起作用,但我实际上是按标签对帖子进行分组,结果组就是需要分页的。
【解决方案2】:
  1. 使用$projecttagcount 保存到tmp
  2. 使用$pushaddToSettmp 存储到您的data 列表中。

代码:

db.test.aggregate(
    {$unwind: '$tags'}, 
    {$group:{_id: '$tags', count:{$sum:1}}},
    {$project:{tmp:{tag:'$_id', count:'$count'}}}, 
    {$group:{_id:null, total:{$sum:1}, data:{$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
}

【讨论】:

  • 我不知道您可以在 $project 管道的新字段中包含多个字段。这正是我所需要的。谢谢。
  • 是否可以使用此方法对数据进行$sort、$skip 或$limit?您不能在 $project 之前限制数据,而且我看不到在不丢失“总数”的情况下这样做的方法。此外,{$sort:{'data.count': 1}} 似乎不像在非聚合查询中那样正常工作。
  • @MichaelDePetrillo,看看这个stackoverflow.com/questions/20348093/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-15
  • 2011-01-22
  • 2011-01-08
相关资源
最近更新 更多