MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Moyenne d'un champ de sous-document dans tous les documents dans Mongo

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