Tout le monde. Dans mongo group query, le résultat affiche uniquement la ou les clés dans les arguments. Comment conserver le premier document de chaque groupe comme le groupe de requêtes mysql. par exemple:
-------------------------------------------------------------------------
| 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 } })
résultat:
[
{
"name" : "ddl1st",
"count" : 1
},
{
"name" : "24k",
"count" : 1
}
]
Comment obtenir les éléments suivants:
[
{
"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
}
]
{$first: '$age'}
etc.? Est-il possible d'avoir justeage: $age
?$group
_id, vous pouvez$sort
auparavant avec le champ souhaité, puis regrouper et utiliser$first
ou$last
opérateurs sur n'importe quel champ. Lors de l'accumulation, l'idée d'inclure d'autres champs (qui sont accumulés / canalisés / réduits) n'a pas beaucoup de sens, même théoriquement. Cependant, le tri préalable est en fait inefficace par rapport au tri de chaque groupe en eux-mêmes car les algorithmes de tri sont plus complexes que O (n). Je souhaite qu'il y ait de meilleures façons dans MongoDB.Au fait, si vous souhaitez conserver non seulement le premier document, vous pouvez utiliser $ addToSet Par exemple:
db.test.aggregate({ $group: { _id: '$name', name : { $addToSet: '$name' } age : { $addToSet: '$age' }, count: { $sum: 1 } } }
la source
[modifié pour inclure des suggestions de commentaires]
Je suis venu ici à la recherche d'une réponse mais je n'étais pas satisfait de la réponse choisie (surtout compte tenu de son âge). J'ai trouvé cette réponse qui est une meilleure solution (adaptée):
db.test.aggregate({ $group: { _id: '$name', person: { "$first": "$$ROOT" }, count: { $sum: 1 } }, { "$replaceRoot": { "newRoot": { "$mergeObjects": ["$person", { count: "$count" }]} } } }
la source
count
champ. Vous devez l'utiliser$mergeObjects
pour le garder.{"$replaceRoot": {"newRoot": {"$mergeObjects": ["$person", {count: "$count"}]}}}
Vous pouvez essayer ceci
db.test.aggregate({ { $group: { _id: '$name',count: { $sum: 1 }, data: { $push: '$$ROOT' } } }, { $project: { _id:0, data:1, count :1 } } }
la source
C'est ce que j'ai fait, ça marche bien.
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 } }])
la source
Juste une mise à jour rapide si l'on rencontre le même problème avec des documents avec de nombreux champs. On peut utiliser la puissance de la combinaison de l'
$replaceRoot
étage du$mergeObjects
pipeline et de l' exploitant du pipeline.db.users.aggregate([ { $group: { _id: '$name', user: { $first: '$$ROOT' }, count: { $sum: 1 } }, }, { $replaceRoot: { newRoot: { $mergeObjects: [{ count: '$count' }, '$user'] } } } ])
la source
Utiliser
$first
avec le$$ROOT
document, puis utiliser$replaceRoot
avec le premier champ.db.test.aggregate([ { "$group": { "_id": "$name", "doc": { "$first": "$$ROOT" } }}, { "$replaceRoot": { "newRoot": "$doc" }} ])
la source
Je ne connaissais pas
.group
helper, mais si vous préférez utiliser le Framework d'agrégation , vous devrez spécifier les champs à renvoyer. Corrigez-moi si je me trompe, mais en SQL, vous devrez le faire de toute façon.Eh bien, voici comment vous le feriez avec le cadre d'agrégation mentionné précédemment:
db.test.aggregate({ $group: { _id: { name: "$name", city: "$city", fieldName: "$fieldName" }, count: { $sum: 1 } } })
la source
J'ai créé cette fonction pour généraliser l'inversion d'une étape de déroulement ... faites-moi savoir si vous rencontrez des bugs avec elle, mais cela fonctionne bien pour moi!
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 }
la source
Si vous souhaitez projeter tous les champs, utilisez la requête ci-dessous.
db.persons.aggregate({ { $group: { _id: '$name', data: { $push: '$$ROOT' }, total: { $sum: 1 }} }, { $project: { _id:0, data:1, total :1 } } }
la source
Voici la réponse >>>>
$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();
la source