如何保存字段的 mongo 组查询

所有人。 在 mongo 组查询中,结果只显示参数中的键。如何保持每个组中的第一个文档,如 mysql 查询组。 例如:

-------------------------------------------------------------------------
|  name  | age  |  sex  | province |   city   |   area   |   address     |
-------------------------------------------------------------------------
| ddl1st | 22   | 纯爷们 |  BeiJing |  BeiJing | ChaoYang | QingNianLu    |
| ddl1st | 24   | 纯爷们 |  BeiJing |  BeiJing | XuHui    | ZhaoJiaBangLu |
|  24k   | 220  | ...   |  ....    |  ...     | ...      | ...           |
-------------------------------------------------------------------------






db.users.group({key: { name: 1},reduce: function ( curr, result ) { result.count ++ },initial: {count : 0 } })

结果:

[
{
"name" : "ddl1st",
"count" : 1
},
{
"name" : "24k",
"count" : 1
}
]

如何取得以下资料:

[
{
"name" : "ddl1st",
"age" : 22,
"sex" : "纯爷们",
"province" : "BeiJing",
"city" : "BeiJing",
"area" : "ChaoYang",
"address" : "QingNianLu",
"count" : 1
},
{
"name" : "24k",
"age" : 220,
"sex" : "...",
"province" : "...",
"city" : "...",
"area" : "...",
"address" : "...",
"count" : 1
}
]
119820 次浏览

我不知道 .group助手,但是如果您喜欢使用 聚合框架,那么您必须指定返回哪些字段。如果我说错了请纠正我,但是在 SQL 中你无论如何都要这样做。

好吧,这就是如何使用前面提到的聚合框架:

db.test.aggregate({
$group: {
_id: { name: "$name", city: "$city", fieldName: "$fieldName" },
count: { $sum: 1 }
}
})

如果希望保留每个组的第一个匹配条目的信息,可以尝试如下聚合:

    db.test.aggregate([{
$group: {
_id : '$name',
name : { $first: '$name' },
age : { $first: '$age' },
sex : { $first: '$sex' },
province : { $first: '$province' },
city : { $first: '$city' },
area : { $first: '$area' },
address : { $first: '$address' },
count : { $sum: 1 },
}
}]);

这是答案

    $m = new \MongoDB\Driver\Manager();


$command = new \MongoDB\Driver\Command([
'aggregate' => 'mytestusers',
'pipeline' => [
['$match' => ['name' => 'Pankaj Choudhary']],


['$unwind'=>'$skills'],
['$lookup' => array('from'=>'mytestskills','localField'=>'skills','foreignField'=>'_id','as'=>'sdfg')],
['$unwind'=>'$sdfg'],


['$group'=>array('_id'=>array('_id'=>'$_id','name'=>'$name','email'=>'$email'),'skills'=>array('$push'=>'$skills'),'sdfg'=>array('$push'=>'$sdfg'))],




],
'cursor' => new \stdClass,
]);
$cursor = $m->executeCommand('targetjob-plus', $command);
$result = $cursor->toArray();

[编辑加入评论建议]

我来这里寻找一个答案,但不满意所选择的答案(特别是考虑到它的年龄)。我发现 这个答案是一个更好的解决方案(改编) :

db.test.aggregate({
$group: {
_id: '$name',
person: { "$first": "$$ROOT" },
count: { $sum: 1 }
},
{
"$replaceRoot": { "newRoot": { "$mergeObjects": ["$person", { count: "$count" }]} }
}
}

顺便说一下,如果您不想只保留第一个文档,那么可以使用 < a href = “ https://docs.mongodb.com/Manual/reference/Operating/addToSet/”rel = “ norefrer”> $addToSet 例如:

db.test.aggregate({
$group: {
_id: '$name',
name : { $addToSet: '$name' }
age : { $addToSet: '$age' },
count: { $sum: 1 }
}
}

你可以试试这个

db.test.aggregate({
{ $group:
{ _id: '$name',count: { $sum: 1 }, data: { $push: '$$ROOT' } } },
{
$project: {
_id:0,
data:1,
count :1
}
}


}

我就是这么做的,效果很好。

db.person.aggregate([
{
$group: { _id: '$name'}, // pass the set of field to be grouped
age : { $first: '$age' }, // retain remaining field
count: { $sum: 1 } // count based on your group
},
{
$project:{
name:"$_id.name",
age: "$age",
count: "$count",
_id:0
}
}])

我创建了这个函数来泛化逆转一个放松阶段... 让我知道,如果你们遇到任何错误与它,但它工作得很好!

const createReverseUnwindStages = unwoundField => {
const stages = [
//
// Group by the unwound field, pushing each unwound value into an array,
//
// Store the data from the first unwound document
// (which should all be the same apart from the unwound field)
// on a field called data.
// This is important, since otherwise we have to specify every field we want to keep individually.
//
{
$group: {
_id: '$_id',
data: {$first: '$$ROOT'},
[unwoundField]: {$push: `$${unwoundField}`},
},
},


//
// Copy the array of unwound fields resulting from the group into the data object,
// overwriting the singular unwound value
//
{
$addFields: {[`data.${unwoundField}`]: `$${unwoundField}`},
},


//
// Replace the root with our data object
//
{
$replaceRoot: {
newRoot: '$data',
},
},
]


return stages
}

只是一个快速更新,如果一个人面临同样的问题与文件的许多领域。 一个可以使用功率相结合的 $replaceRoot管道阶段和 $mergeObjects管道运营商。

db.users.aggregate([
{
$group: {
_id: '$name',
user: { $first: '$$ROOT' },
count: { $sum: 1 }
},
},
{
$replaceRoot: {
newRoot: { $mergeObjects: [{ count: '$count' }, '$user'] }
}
}
])

$$ROOT文档使用 强 > $first,然后对第一个字段使用 $replaceRoot

db.test.aggregate([
{ "$group": {
"_id": "$name",
"doc": { "$first": "$$ROOT" }
}},
{ "$replaceRoot": { "newRoot": "$doc" }}
])

如果要投影所有字段,请在查询下面使用此文档。

db.persons.aggregate({
{ $group: { _id: '$name', data: { $push: '$$ROOT' }, total: { $sum: 1 }} },
{
$project: {
_id:0,
data:1,
total :1
}
}
}

我喜欢将 $first 选项将要使用的所有内容都放到一个 dictionary 中,以便在最后提取。

{'$set':
{'collection_name':
'collection_item1': '$collection_item1',
'collection_item2': '$collection_item2',
...
}
}

现在,只要复制字典,你就不必再一次背着所有这些信息了!

{'$group':
'_id': ['$id'],
'collection_name': {'$first': '$collection_name'}
}