Supposons que vous ayez les documents suivants dans ma collection:
{
"_id":ObjectId("562e7c594c12942f08fe4192"),
"shapes":[
{
"shape":"square",
"color":"blue"
},
{
"shape":"circle",
"color":"red"
}
]
},
{
"_id":ObjectId("562e7c594c12942f08fe4193"),
"shapes":[
{
"shape":"square",
"color":"black"
},
{
"shape":"circle",
"color":"green"
}
]
}
Faire une requête:
db.test.find({"shapes.color": "red"}, {"shapes.color": 1})
Ou
db.test.find({shapes: {"$elemMatch": {color: "red"}}}, {"shapes.color": 1})
Renvoie le document correspondant (Document 1) , mais toujours avec TOUS les éléments du tableau dans shapes
:
{ "shapes":
[
{"shape": "square", "color": "blue"},
{"shape": "circle", "color": "red"}
]
}
Cependant, je voudrais obtenir le document (Document 1) uniquement avec le tableau qui contient color=red
:
{ "shapes":
[
{"shape": "circle", "color": "red"}
]
}
Comment puis-je faire ceci?
aggregate
.db.test.find({}, {shapes: {$elemMatch: {color: "red"}}});
Le nouveau cadre d'agrégation dans MongoDB 2.2+ offre une alternative à Map / Reduce. L'
$unwind
opérateur peut être utilisé pour séparer votreshapes
tableau en un flux de documents pouvant être mis en correspondance:Résulte en:
la source
$elemMatch
c'est une autre option. En fait, je suis arrivé ici par le biais d'une question du groupe Google où $ elemMatch ne fonctionnerait pas, car il ne renvoie que la première correspondance par document.{ $project : { shapes : 1 } }
- ce qui semblait fonctionner et serait utile si les documents joints étaient volumineux et que vous vouliez simplement afficher lesshapes
valeurs clés.Une autre façon intéressante est d'utiliser $ redact , qui est l'une des nouvelles fonctionnalités d'agrégation de MongoDB 2.6 . Si vous utilisez 2.6, vous n'avez pas besoin d'un déroulement $ qui pourrait vous causer des problèmes de performances si vous avez de grands tableaux.
$redact
"restreint le contenu des documents sur la base des informations stockées dans les documents eux-mêmes" . Il ne s'exécutera donc qu'à l' intérieur du document . Il analyse essentiellement votre document de haut en bas et vérifie s'il correspond à votreif
condition$cond
, s'il y a correspondance, il conservera le contenu ($$DESCEND
) ou supprimera ($$PRUNE
).Dans l'exemple ci-dessus,
$match
renvoie d' abord leshapes
tableau entier , et $ redact le supprime jusqu'au résultat attendu.Notez que cela
{$not:"$color"}
est nécessaire, car il numérisera également le document supérieur, et s'il$redact
ne trouve pas decolor
champ au niveau supérieur, cela retournerafalse
qui pourrait supprimer tout le document dont nous ne voulons pas.la source
$match
comme première étape agrégéeLe paramètre de sélection de champ est limité aux propriétés complètes. Il ne peut pas être utilisé pour sélectionner une partie d'un tableau, uniquement le tableau entier. J'ai essayé d'utiliser l' opérateur $ positional , mais cela n'a pas fonctionné.
Le moyen le plus simple consiste à simplement filtrer les formes dans le client .
Si vous avez vraiment besoin de la sortie correcte directement depuis MongoDB, vous pouvez utiliser une carte-réduire pour filtrer les formes.
la source
Mieux, vous pouvez interroger l'élément de tableau correspondant en utilisant
$slice
est-il utile de renvoyer l'objet significatif dans un tableau.$slice
est utile lorsque vous connaissez l'index de l'élément, mais que vous souhaitez parfois que l'élément de tableau corresponde à vos critères. Vous pouvez renvoyer l'élément correspondant avec l'$
opérateur.la source
LES SORTIES
la source
La syntaxe pour trouver dans mongodb est
et la deuxième requête que vous avez écrite, c'est
en cela, vous avez utilisé l'
$elemMatch
opérateur dans la partie requête, alors que si vous utilisez cet opérateur dans la partie projection, vous obtiendrez le résultat souhaité. Vous pouvez écrire votre requête sous la formeCela vous donnera le résultat souhaité.
la source
"shapes.color":"red"
dans le paramètre de requête (le premier paramètre de la méthode find) n'est pas nécessaire. Vous pouvez le remplacer par{}
et obtenir les mêmes résultats.Merci à JohnnyHK .
Ici, je veux juste ajouter une utilisation plus complexe.
la source
Vous avez juste besoin d'exécuter la requête
la sortie de cette requête est
comme vous vous y attendiez, le champ exact du tableau correspond à la couleur: «rouge».
la source
avec $ project, il sera plus approprié que d'autres éléments d'appariement judicieux soient regroupés avec d'autres éléments dans le document.
la source
De même, vous pouvez trouver pour les multiples
la source
$match
pour réduire l'espace, puis$filter
pour conserver ce que vous voulez, en écrasant le champ de saisie (utilisez la sortie de$filter
sur le champshapes
pour$project
revenir surshapes
. Note de style: mieux vaut ne pas utiliser le nom du champ comme l'as
argument car cela peut prêter à confusion plus tard avec$$shape
et$shape
. Je préfèrezz
commeas
terrain car il se démarque vraiment.la source
Utiliser la fonction d'agrégation et
$project
pour obtenir un champ d'objet spécifique dans le documentrésultat:
la source
Bien que la question ait été posée il y a 9,6 ans, cela a été d'une immense aide pour de nombreuses personnes, dont moi-même. Merci à tous pour toutes vos questions, conseils et réponses. Reprenant l'une des réponses ici .. J'ai trouvé que la méthode suivante peut également être utilisée pour projeter d'autres champs dans le document parent. Cela peut être utile à quelqu'un.
Pour le document suivant, la nécessité était de savoir si un employé (emp # 7839) avait son historique de congés défini pour l'année 2020. L'historique des congés est implémenté en tant que document incorporé dans le document Employé parent.
la source