Vous devrez utiliser le cadre d'agrégation. L'agrégation finira par ressembler à ceci :
db.stack.aggregate([
{ $match: { "samples.key" : "test-key" } },
{ $unwind : "$samples" },
{ $match : { "samples.key" : "test-key" } },
{ $project : { "new_key" : "$samples.key", "new_value" : "$samples.value" } },
{ $group : { `_id` : "$new_key", answer : { $avg : "$new_value" } } }
])
La meilleure façon de penser au cadre d'agrégation est comme une chaîne de montage. La requête elle-même est un tableau de documents JSON, où chaque sous-document représente une étape différente de l'assemblage.
Étape 1 :$match
La première étape est un filtre de base, comme une clause WHERE dans SQL. Nous plaçons cette étape en premier pour filtrer tous les documents qui ne contiennent pas d'élément de tableau contenant test-key
. Le placer au début du pipeline permet à l'agrégation d'utiliser des index.
Étape 2 :$déroulez
La deuxième étape, $unwind
, est utilisé pour séparer chacun des éléments du tableau "samples" afin que nous puissions effectuer des opérations sur chacun d'eux. Si vous exécutez la requête avec juste cette étape, vous verrez ce que je veux dire. Pour faire court :
{ name : "bob",
children : [ {"name" : mary}, { "name" : "sue" } ]
}
devient deux documents :
{ name : "bob", children : [ { "name" : mary } ] }
{ name : "bob", children : [ { "name" : sue } ] }
Étape 3 :$match
La troisième étape, $match
, est une copie exacte du premier $match
étape, mais a un but différent. Puisqu'il suit $unwind
, cette étape filtre les éléments de tableau précédents, désormais des documents, qui ne correspondent pas aux critères de filtrage. Dans ce cas, nous ne conservons que les documents où samples.key = "test-key"
Étape 4 :$project (facultatif)
La quatrième étape, $project
, restructure le document. Dans ce cas, j'ai retiré les éléments du tableau afin de pouvoir les référencer directement. En utilisant l'exemple ci-dessus..
{ name : "bob", children : [ { "name" : mary } ] }
devient
{ new_name : "bob", new_child_name : mary }
Notez que cette étape est entièrement facultative; les étapes ultérieures pourraient être complétées même sans ce $project
après quelques modifications mineures. Dans la plupart des cas, $project
est entièrement cosmétique ; les agrégations ont de nombreuses optimisations sous le capot telles que l'inclusion ou l'exclusion manuelle de champs dans un $project
ne devrait pas être nécessaire.
Étape 5 :$groupe
Enfin, $group
c'est là que la magie opère. Le _id
évaluez ce que vous allez "regrouper par" dans le monde SQL. Le deuxième champ dit de faire la moyenne sur la valeur que j'ai définie dans le $project
étape. Vous pouvez facilement remplacer $sum
pour effectuer une somme, mais une opération de comptage se fait généralement de la manière suivante :my_count : { $sum : 1 }
.
La chose la plus importante à noter ici est que la majorité du travail effectué consiste à formater les données à un point où l'exécution de l'opération est simple.
Remarque finale
Enfin, je voulais noter que cela ne serait pas travailler sur les exemples de données fournis depuis samples.value
est défini comme du texte, qui ne peut pas être utilisé dans les opérations arithmétiques. Si cela vous intéresse, la modification du type d'un champ est décrite ici :MongoDB Comment modifier le type d'un champ