sql >> Base de Datos >  >> NoSQL >> MongoDB

$desenrollar un objeto en el marco de agregación

No es posible realizar el tipo de cálculo que está describiendo con el marco de agregación, y no porque no hay $unwind método para no arreglos. Incluso si los objetos person:value fueran documentos en una matriz, $unwind no ayudaría.

La funcionalidad de "agrupar por" (ya sea en MongoDB o en cualquier base de datos relacional) se realiza sobre el valor de un campo o columna. Agrupamos por valor de campo y suma/promedio/etc. en función del valor de otro campo.

El ejemplo simple es una variante de lo que sugiere, el campo de calificaciones agregado a la colección de artículos de ejemplo, pero no como un mapa del usuario a la calificación, sino como una matriz como esta:

{ title : title of article", ...
  ratings: [
         { voter: "user1", score: 5 },
         { voter: "user2", score: 8 },
         { voter: "user3", score: 7 }
  ]
}

Ahora puede agregar esto con:

[ {$unwind: "$ratings"},
  {$group : {_id : "$ratings.voter", averageScore: {$avg:"$ratings.score"} } } 
]

Pero este ejemplo estructurado como usted lo describe se vería así:

{ title : title of article", ...
  ratings: {
         user1: 5,
         user2: 8,
         user3: 7
  }
}

o incluso esto:

{ title : title of article", ...
  ratings: [
         { user1: 5 },
         { user2: 8 },
         { user3: 7 }
  ]
}

Incluso si pudieras $unwind esto, no hay nada que agregar aquí. A menos que conozca la lista completa de todas las claves posibles (usuarios), no puede hacer mucho con esto. [*]

Un esquema de base de datos relacional análogo al que tiene sería:

CREATE TABLE T (
   user1: integer,
   user2: integer,
   user3: integer
   ...
);

Eso no es lo que se haría, sino que haríamos esto:

CREATE TABLE T (
   username: varchar(32),
   score: integer
);

y ahora agregamos usando SQL:

select username, avg(score) from T group by username;

Hay una solicitud de mejora para MongoDB que puede permitirle hacer esto en el marco de agregación en el futuro:la capacidad de proyectar valores a claves y viceversa. Mientras tanto, siempre hay map/reduce.

[*] Hay una manera complicada de hacer esto si conoce todas las claves únicas (puede encontrar todas las claves únicas con un método similar a este), pero si conoce todas las claves, también puede ejecutar una secuencia de consultas del formulario db.articles.find({"ratings.user1":{$exists:true}},{_id:0,"ratings.user1":1}) para cada usuarioX que devolverá todas sus calificaciones y puede sumarlas y promediarlas de manera bastante simple en lugar de hacer una proyección muy compleja que requeriría el marco de agregación.