如何计算同一MongoDB聚合$ group查询中的多个键?

时间:2013-05-16 21:28:58

标签: mongodb aggregation-framework

我有一个问题:

db.test.aggregate( {$group : { _id : '$key', frequency: { $sum : 1 } } } )

这将获得测试集中每个密钥枚举的频率。基本上,我已经获得了密钥的分发。

现在想象一下我想得到key1,key2和key3的分布(所以有三种不同的分布)。

显然,我可以使用每个单独的密钥运行此查询3次,但似乎我们可以通过允许它同时计算所有3个密钥来优化查询。我一直在玩它并搜索整个网络间,但到目前为止,我被委托运行三个单独的聚合查询或使用map / reduce函数。

有没有人有其他想法?

1 个答案:

答案 0 :(得分:6)

您可以在此处使用几种不同的方法:

  1. 使用map / reduce:不要这样做。现在,运行聚合框架3次比使用map reduce函数要快得多。

  2. 运行聚合3次。这不是最佳选择,但如果您没有时间限制,那么这是最简单的选择。如果您的聚合正在进行<无论如何几秒钟,我不会担心优化,直到它们成为一个问题。

  3. 这是我能想到的最好的解决方法。 $group运算符允许您在多个字段上构建_id。例如。 {"_id":{"a":"$key1", "b":"$key2", "c":"$key3"}}。这样做会为不同键的所有现有组合创建分组。您可以通过这种方式对密钥进行分组,然后在客户端中手动对结果进行求和。

  4. 让我详细说明一下。假设我们有一组形状。这些形状可以具有颜色,大小和种类(方形,圆形等)。多键ID上的聚合可能如下所示:

    db.shapes.aggregate({$group:{_id:{"f1":"$f1", "f2":"$f2", "f3":"$f3"}, count:{"$sum":1}}})
    

    并返回:

    "result" : [
            {
                "_id" : {
                    "f1" : "yellow",
                    "f2" : "medium",
                    "f3" : "triangle"
                },
                "count" : 4086
            },
            {
                "_id" : {
                    "f1" : "red",
                    "f2" : "small",
                    "f3" : "triangle"
                },
                "count" : 4138
            },
            {
                "_id" : {
                    "f1" : "red",
                    "f2" : "big",
                    "f3" : "square"
                },
                "count" : 4113
            },
            {
                "_id" : {
                    "f1" : "yellow",
                    "f2" : "small",
                    "f3" : "triangle"
                },
                "count" : 4145
            },
            {
                "_id" : {
                    "f1" : "red",
                    "f2" : "small",
                    "f3" : "square"
                },
                "count" : 4062
            }
    

    ......等等

    然后,您将通过大幅减少的条目数量总结客户端的结果。假设每个密钥的唯一值数量与文档总数相比足够小,您可以在一个可忽略的时间内完成最后一步。