El operador de expresión agregada personalizado completa principalmente operaciones de consulta agregadas más complejas mediante la personalización de algunas funciones de Javascript; en este artículo, presentamos principalmente el uso de $acumulador :
1. Preparación
Inicializar datos de calificación del curso
db.subjectScores.insertMany([
{ "_id": 1, "name": "张三", "subject": "eng", "score": 80 },
{ "_id": 2, "name": "李四", "subject": "eng", "score": 60 },
{ "_id": 3, "name": "王五", "subject": "eng", "score": 90 },
{ "_id": 4, "name": "张三", "subject": "math", "score": 70 },
{ "_id": 5, "name": "李四", "subject": "math", "score": 90 },
{ "_id": 6, "name": "王五", "subject": "math", "score": 50 },
{ "_id": 7, "name": "张三", "subject": "physics", "score": 80 },
{ "_id": 8, "name": "李四", "subject": "physics", "score": 60 },
{ "_id": 9, "name": "王五", "subject": "physics", "score": 70 }
])
dos, $ acumulador
gramática:
{
$accumulator: {
init: <code>,
initArgs: <array expression>, // Optional
accumulate: <code>,
accumulateArgs: <array expression>,
merge: <code>,
finalize: <code>, // Optional
lang: <string>
}
}
init: la función se usa para inicializar el objeto de estado y recibir parámetros de initArgs
function (<initArg1>, <initArg2>, ...) {
...
return <initialState>
}
initArgs: opcional, lista de parámetros de inicialización
[ <initArg1>, <initArg2>, ... ]
acumular: La función se utiliza para acumular documentos, el primer parámetro es el objeto de estado, los demás parámetros se reciben de acumulaArgs; devuelve un nuevo objeto de estado
function(state, <accumArg1>, <accumArg2>, ...) {
...
return <newState>
}
acumulaArgs: lista de argumentos acumulados
[ <accumArg1>, <accumArg2>, ... ]
fusionar: la función se utiliza para fusionar dos objetos de estado; devuelve un nuevo objeto de estado
function (<state1>, <state2>) {
<logic to merge state1 and state2>
return <newState>
}
finalizar: la función se utiliza para devolver el resultado de la agregación
function (state) {
...
return <finalState>
}
lang: el idioma utilizado, actualmente solo admite js
$accumulator solo se puede usar en 4.4 y versiones posteriores
3. Ejemplo: Calcular la puntuación total de los alumnos
Las consultas de agregación son las siguientes:
db.subjectScores.aggregate([
{
$group: {
"_id": "$name",
"score": {
$accumulator: {
init: function() {
return {
sum: 0
}
},
accumulate: function(state, score) {
return {
sum: state.sum + score
}
},
accumulateArgs: [ "$score" ],
merge: function(state1, state2) {
return {
sum: state1.sum + state2.sum
}
},
finalize: function(state) {
return state.sum
},
lang: "js"
}
}
}
}
])
Explicamos la consulta de agregación anterior:
1. Agrupe los documentos de calificación del curso por nombre
2. Inicializar el objeto de estado y acumular y sumar las puntuaciones en los documentos de entrada
3. Combinar objetos de estado
4. Devuelva el valor de la suma en el objeto de estado como la puntuación total
La consulta de agregación anterior es equivalente a:
db.subjectScores.aggregate([
{
$group: {
"_id": "$name",
"score": { $sum: "$score" }
}
}
])
Los resultados de la consulta de agregación son los siguientes:
{ "_id" : "王五", "score" : 210 }
{ "_id" : "李四", "score" : 210 }
{ "_id" : "张三", "score" : 230 }