Je viens de me retrouver avec ce problème. J’ai deux schémas Mongoose:
var childrenSchema = mongoose.Schema({ name: { type: Ssortingng }, age: { type: Number, min: 0 } }); var parentSchema = mongoose.Schema({ name : { type: Ssortingng }, children: [childrenSchema] });
La question est, comment récupérer tous les sous-documents (dans ce cas, les objects childrenSchema
) de chaque document parent? Supposons que j’ai des données:
var parents = [ { name: "John Smith", children: [ { name: "Peter", age: 2 }, { name: "Margaret", age: 20 } ]}, { name: "Another Smith", children: [ { name: "Martha", age: 10 }, { name: "John", age: 22 } ]} ];
Je voudrais récupérer – en une seule requête – tous les enfants de plus de 18 ans. Est-ce possible? Chaque réponse sera appréciée, merci!
Vous pouvez utiliser $elemMatch
tant qu’opérateur de projection de requête dans les versions les plus récentes de MongoDB. De la coquille de mongo:
db.parents.find( {'children.age': {$gte: 18}}, {children:{$elemMatch:{age: {$gte: 18}}}})
Ceci filtre les documents des plus jeunes enfants du tableau des children
:
{ "_id" : ..., "children" : [ { "name" : "Margaret", "age" : 20 } ] } { "_id" : ..., "children" : [ { "name" : "John", "age" : 22 } ] }
Comme vous pouvez le constater, les enfants sont toujours regroupés dans leurs documents parents. Les requêtes MongoDB renvoient des documents à partir de collections. Vous pouvez utiliser la méthode $unwind
du framework d’agrégation pour les scinder en documents distincts:
> db.parents.aggregate({ $match: {'children.age': {$gte: 18}} }, { $unwind: '$children' }, { $match: {'children.age': {$gte: 18}} }, { $project: { name: '$children.name', age:'$children.age' } }) { "result" : [ { "_id" : ObjectId("51a7bf04dacca8ba98434eb5"), "name" : "Margaret", "age" : 20 }, { "_id" : ObjectId("51a7bf04dacca8ba98434eb6"), "name" : "John", "age" : 22 } ], "ok" : 1 }
Je répète la clause $match
pour l’exécution: la première fois, elle élimine les parents sans enfant de 18 ans au moins, de sorte que le $unwind
ne considère que les documents utiles. La deuxième $match
supprime la sortie $unwind
qui ne correspond pas et le $project
extrait les informations relatives aux enfants des sous-documents au niveau supérieur.
En Mongoose, vous pouvez également utiliser la fonction élégante .populate()
comme ceci:
parents .find({}) .populate({ path: 'children', match: { age: { $gte: 18 }}, select: 'name age -_id' }) .exec()