11

我正在尝试做一些我认为很简单的事情。假设我在 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

4 回答 4

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
}
于 2012-08-31T05:01:00.090 回答
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
)
于 2013-02-11T05:32:39.467 回答
0

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

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

我们编写了一个这样的方法来处理“按 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 的其余数据填充它们。

于 2013-10-18T15:06:55.087 回答
-1

用于$addToSet组,它会工作

db.data.aggregate(
    { $group : {
            _id : "$Name",
            x: { $addToSet: "$x" },
            y: { $addToSet: "$y" },
            z: { $addToSet: "$z" },
    }}
)
于 2013-06-19T05:53:44.547 回答