在mongo聚合中选择* group by

时间:2012-08-31 04:08:34

标签: mongodb

我正在尝试做一些我觉得很简单的事情。假设我在mongo中有一系列记录,它们具有公共密钥和可变数量的属性。我想在记录中选择所有属性并按名称分组。例如

{ Name: George, x: 5, y: 3 }
{ Name: George, z: 9 }
{ Name: Rob, x: 12, y: 2 }

我想制作一个如下所示的CSV:

Name     X   Y   Z
George   5   3   9
Rob      12  2

尝试

DB.data.aggregate({ $group : { _id : "$Name" } })

不幸的是,我将所有名称作为记录返回,但不是所有可能属性的联合。

4 个答案:

答案 0 :(得分:11)

如果要合并属性,则需要将这些属性添加到group。例如,使用$addToSet查找按名称分组的x,y,z属性的唯一值:

db.data.aggregate(
    { $group : {
            _id : "$Name",
            x: { $addToSet: "$x" },
            y: { $addToSet: "$y" },
            z: { $addToSet: "$z" },
    }}
)

返回:

{
    "result" : [
        {
            "_id" : "Rob",
            "x" : [
                12
            ],
            "y" : [
                2
            ],
            "z" : [ ]
        },
        {
            "_id" : "George",
            "x" : [
                5
            ],
            "y" : [
                3
            ],
            "z" : [
                9
            ]
        }
    ],
    "ok" : 1
}

答案 1 :(得分:0)

以下是另一种方法:

$connection = 'mongodb://localhost:27017';
$con        = new Mongo($connection); // mongo connection

$db         = $con->test; /// database
$collection = $db->prb; // table

$keys       = array("Name" => 1,"x"=>1,"y"=>1,"z"=>1);

// set intial values
$initial    = array("count" => 0);

// JavaScript function to perform
$reduce     = "function (obj, prev) { prev.count++; }";

$g          = $collection->group($keys, $initial, $reduce);

echo "<pre>";
print_r($g);

你会得到这样的答案(不是确切的输出):

Array
(
    [retval] => Array
        (
            [0] => Array
                (
                    [Name] => George
                    [x] => 
                    [y] =>
                    [z] =>
                    [count] => 2
                )

            [1] => Array
                (
                    [Name] => Rob
                    [x] => 
                    [y] =>
                    [z] =>
                    [count] => 1
                )

        )

    [count] => 5
    [keys] => 3
    [ok] => 1
)

答案 2 :(得分:0)

Stennie的解决方案要求您确切地知道要从您查询的集合中的每个匹配项返回哪些属性。情况并非总是如此。

我们必须在我们正在撰写的Grails应用程序的Groovy中解决这个问题。

我们写了一个这样的方法来处理“通过X查找”请求:

private List<DBObject> findDistinctPages(Map by) {
    def command =
        new GroupCommand(
                (DBCollection) db.pages,
                new BasicDBObject(['url': 1]),
                new BasicDBObject(by),
                new BasicDBObject([:]),
                'function ( current, result ) { for(i in current) { result[i] = current[i] } }',
                ''
        )
    db.pages.group(command).sort { it.title }
}

然后在我们的代码中调用它,如下所示:

def pages = findDistinctPages([$or: [[type: 'channel'], [type: 'main']]])

这可以通过将初始查询的结果传递给GroupCommand末尾的javascript函数来实现。 Mongo只返回您在初始查询中指定的属性而不返回任何其他内容,因此您必须第二次迭代结果,并使用mongo中的其余数据填充它们。

答案 3 :(得分:-1)

$addToSet用于该群组,它将起作用

db.data.aggregate(
    { $group : {
            _id : "$Name",
            x: { $addToSet: "$x" },
            y: { $addToSet: "$y" },
            z: { $addToSet: "$z" },
    }}
)