【问题标题】:Get the firsts aggregated results and aggregate all others in additional element获取第一个聚合结果并在附加元素中聚合所有其他结果
【发布时间】:2017-01-27 15:10:57
【问题描述】:

我需要从查询中获取前 N 个项目,并将所有其他项目(不在 N 前)分组到一个附加元素中。

例如,考虑包含以下文档的集合:

{user: "Ana", post: "A" },
{user: "Ana", post: "B" },
{user: "Ana", post: "C" },
{user: "Ana", post: "D" },
{user: "Bruce", post: "E" },
{user: "Bruce", post: "F" },
{user: "Bruce", post: "G" },
{user: "Cami", post: "H" },
{user: "Cami", post: "I" },
{user: "John", post: "J" },
{user: "Peter", post: "K" },
{user: "Helena", post: "L" }

我希望获得贡献最多的 2 个用户,并将所有其他用户汇总到一个额外的输出项中。例如:

{user: "Ana", count: 4},
{user: "Bruce", count: 3},
{user: "All others guys", count: 5}

现在我正在使用“聚合”功能:

db.MyTest.aggregate(
[
    {
        $group: {
            "_id": "$user",
            count: {
                $sum: 1
            }
        }
    },
    {
        $sort: {
            count: -1,
            userName: 1
        }
    }
]
);

我不知道如何对待“所有其他人”项目。我的函数返回以下结果:

{_id: "Ana", count: 4},
{_id: "Bruce", count: 3},
{_id: "Cami", count: 2},
{_id: "John", count: 1},
{_id: "Peter", count: 1},
{_id: "Helena", count: 1} 

知道如何通过单个查询直接在 mongo 中执行此操作吗?

P.S.:我使用的是 Mongo 3.2.11。

【问题讨论】:

  • 您的 MongoDB 服务器版本是多少?另外,您能否更新您的问题以显示您到目前为止所做的工作?
  • 嘿chridam,我用你的建议更新了这个问题。谢谢!

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

在排序统计信息后,您可以将所有用户统计信息推送到数组,然后从该数组中按索引获取所需的项目,然后对所有其他项目进行切片以聚合其统计信息:

db.users.aggregate([
    {$group: {_id:"$user", count:{$sum:1}}},
    {$sort: {count:-1}},
    // Split stats into first, second and others
    {$group: {_id:1, users:{$push:{user:"$_id", count:"$count"}}}},
    {$project: {
        first : {$arrayElemAt: ["$users", 0]},
        second: {$arrayElemAt: ["$users", 1]},
        others: {$slice:["$users", 2, {$size: "$users"}]}
      }
    },
    // Calculate count for all other guys
    {$project: {
         stats: [
            "$first",
            "$second",
            {
                user: "All other guys",
                count: {$sum: "$others.count"}
            }
         ]
      }
    },
    // Bring embeded documents to top level
    {$unwind: "$stats"}, 
    {$project: { _id:0, user: "$stats.user", count: "$stats.count" }}        
])

输出:

{
    "user" : "Ana",
    "count" : 4
}, 
{
    "user" : "Bruce",
    "count" : 3
}, 
{
    "user" : "All other guys",
    "count" : 5
}

注意:即使您在数据库中有零个或单个用户,代码也可以工作。但在第二种情况下,您将获得第二个最可发布用户的统计信息的空文档。这很公平。

【讨论】:

  • 嘿,谢尔盖,谢谢伙计,工作就像一个魅力......我在这里做了一个调整:替换这一行:用户:“所有其他人”,为此:用户:{$ifNull:[ null, "All other guy" ]}, 我不知道错误(..."FieldPath 'All other guy' doesn't start with $"...) 是由不同的 mongodb 版本引起的,但现在是工作......我很感激如果你可以调整或在你的答案中添加注释,也许对其他人有用......再次感谢!
猜你喜欢
  • 2014-02-19
  • 2020-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-08
  • 2017-03-31
  • 2014-01-25
相关资源
最近更新 更多