问题 在mongo聚合中选择* group by
我想做一些我觉得很简单的事情。假设我在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" } })
不幸的是,我将所有名称作为记录返回,但不是所有可能属性的联合。
10523
2017-08-31 04:08
起源
答案:
如果要组合属性,则需要将这些属性添加到 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
}
11
2017-08-31 05:01
答案:
如果要组合属性,则需要将这些属性添加到 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
}
11
2017-08-31 05:01
这是另一种方法:
$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
)
0
2018-02-11 05:32
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中的其余数据填充它们。
0
2017-10-18 15:06
使用 $addToSet
对小组来说,它会奏效
db.data.aggregate(
{ $group : {
_id : "$Name",
x: { $addToSet: "$x" },
y: { $addToSet: "$y" },
z: { $addToSet: "$z" },
}}
)
-1
2018-06-19 05:53