mongodb mongo 组查询如何保留字段
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16662405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
mongo group query how to keep fields
提问by plusor
Everybody. In mongo group query, the result shows only the key(s) in arguments. How to keep the first document in each group like mysql query group. for example:
大家。在 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 } })
result:
结果:
[
{
"name" : "ddl1st",
"count" : 1
},
{
"name" : "24k",
"count" : 1
}
]
How to get the following:
如何获得以下内容:
[
{
"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
}
]
回答by MervS
If you want to keep the information about the first matching entries for each group, you can try aggregating like:
如果你想保留每个组的第一个匹配条目的信息,你可以尝试聚合:
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 }
}
}
回答by u5189296
回答by Pieter
I came here looking for an answer but wasn't happy with the selected answer (especially given it's age). I found this answerthat is a better solution (adapted):
我来到这里寻找答案,但对所选答案不满意(特别是考虑到它的年龄)。我发现这个答案是一个更好的解决方案(改编):
db.test.aggregate({
$group: {
_id: '$name',
person: { "$first": "$$ROOT" },
count: { $sum: 1 }
},
{
"$replaceRoot": { "newRoot": "$person" }
}
}
回答by Deeksha Sharma
You can try out this
你可以试试这个
db.test.aggregate({
{ $group:
{ _id: '$name',count: { $sum: 1 }, data: { $push: '$$ROOT' } } },
{
$project: {
_id:0,
data:1,
count :1
}
}
}
回答by Thavaprakash Swaminathan
This is what i did, it works fine.
这就是我所做的,它工作正常。
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
}
}])
回答by Matt Wills
I created this function to generalise reversing an unwind stage... let me know if you guys come across any bugs with it, but it's working well for me!
我创建了这个函数来概括反转放松阶段……如果你们遇到任何错误,请告诉我,但它对我来说效果很好!
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
}
回答by Gary Wild
Just a quick update if one faces the same issue with documents with numerous fields.
One can use the power of combining the $replaceRoot
pipeline stage and the $mergeObjects
pipeline operator.
如果您在处理包含多个字段的文档时遇到同样的问题,只需快速更新即可。可以使用组合$replaceRoot
流水线阶段和$mergeObjects
流水线操作符的力量。
db.users.aggregate([
{
$group: {
_id: '$name',
user: { $first: '$$ROOT' },
count: { $sum: 1 }
},
},
{
$replaceRoot: {
newRoot: { $mergeObjects: [{ count: '$count' }, '$user'] }
}
}
])
回答by Ashh
Use $first
with the $$ROOT
document and then use $replaceRoot
with the first field.
使用$first
与$$ROOT
文档,然后用$replaceRoot
与第一场。
db.test.aggregate([
{ "$group": {
"_id": "$name",
"doc": { "$first": "$$ROOT" }
}},
{ "$replaceRoot": { "newRoot": "$doc" }}
])
回答by gustavohenke
I didn't know about .group
helper, but if you prefer to go with the Aggregation Framework, then you'll have to specify which fields to return. Correct me if I'm wrong, but in SQL you would have to do that anyway.
我不知道.group
helper,但是如果您更喜欢使用Aggregation Framework,那么您必须指定要返回的字段。如果我错了,请纠正我,但在 SQL 中,无论如何您都必须这样做。
Well, this is how you would do it with the Aggregation Framework mentioned before:
好吧,这就是您如何使用前面提到的聚合框架来做到这一点:
db.test.aggregate({
$group: {
_id: { name: "$name", city: "$city", fieldName: "$fieldName" },
count: { $sum: 1 }
}
})
回答by Pankaj Cheema
Here is the answer >>>>
答案在这里>>>
$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();