Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

$reduce (operador de expresión)

$reduce

Aplica una expresión a cada elemento de un arreglo y los combina en un solo valor.

$reduce tiene la siguiente sintaxis:

{
$reduce: {
input: <array>,
initialValue: <expression>,
in: <expression>,
as: <string>,
valueAs: <string>,
arrayIndexAs: <string>
}
}
Campo
Tipo
Descripción

input

arreglo

Puede ser cualquier valor válido expresión que resuelve a un arreglo. Para obtener más información sobre expresiones, consulta Expresiones.

Si el argumento se resuelve en un valor de null o se refiere a un campo que falta, $reduce devuelve null.

Si el argumento no se resuelve en un arreglo o null, ni hace referencia a un campo ausente, $reduce devuelve un error.

initialValue

expresión

El value acumulativo inicial establecido antes de que in se aplique al primer elemento del arreglo input.

in

expresión

Una expresión válida que $reduce se aplica a cada elemento del arreglo input en orden de izquierda a derecha. Envuelve el valor input con $reverseArray para obtener el equivalente de aplicar la expresión de combinación de derecha a izquierda.

Durante la evaluación de la expresión in, habrá dos variables disponibles:

  • value es la variable que representa el valor acumulativo de la expresión.

  • this es la variable que hace referencia al elemento que se está procesando.

as

string

opcional. Un nombre para la variable que representa cada elemento individual del arreglo input. Si se omite, el nombre de la variable será this por defecto.

Nuevo en la versión 8.3.

valueAs

string

opcional. Un nombre para la variable que representa el valor acumulativo de la expresión. Si se omite, el nombre de la variable será value por defecto.

Nuevo en la versión 8.3.

arrayIndexAs

string

opcional. Un nombre para la variable de agregación que representa el índice del elemento actual en el arreglo input. El índice del primer elemento del arreglo es 0.

Puede usar el nombre de la variable en una expresión. Por ejemplo, si se especifica arrayIndexAs: "myIndex", se usa $$myIndex en la expresión. $$myIndex devuelve el índice del elemento actual en el arreglo input.

Si omites arrayIndexAs, puedes utilizar la variable del sistema $$IDX en la expresión para devolver el índice del elemento actual.

Para ejemplos, consulta Accede al índice de cada elemento en un arreglo y Utiliza $$IDX para acceder al índice.

Nuevo en la versión 8.3.

Si input se resuelve en un arreglo vacío, $reduce devuelve initialValue.

Ejemplo
Resultados
{
$reduce: {
input: ["a", "b", "c"],
initialValue: "",
in: { $concat : ["$$value", "$$this"] }
}
}

"abc"

{
$reduce: {
input: [ 1, 2, 3, 4 ],
initialValue: { sum: 5, product: 2 },
in: {
sum: { $add : ["$$value.sum", "$$this"] },
product: { $multiply: [ "$$value.product", "$$this" ] }
}
}
}

{ "sum" : 15, "product" : 48 }

{
$reduce: {
input: [ [ 3, 4 ], [ 5, 6 ] ],
initialValue: [ 1, 2 ],
in: { $concatArrays : ["$$value", "$$this"] }
}
}

[ 1, 2, 3, 4, 5, 6 ]

Una colección denominada events contiene los eventos de un experimento de probabilidad. Cada experimento puede tener varios events, como lanzar un dado varias veces o robar cartas (sin reemplazo) seguidas para lograr un resultado deseado. Para obtener la probabilidad general del experimento, necesitaremos multiplicar la probabilidad de cada evento en el experimento.

db.events.insertMany( [
{ _id : 1, type : "die", experimentId :"r5", description : "Roll a 5", eventNum : 1, probability : 0.16666666666667 },
{ _id : 2, type : "card", experimentId :"d3rc", description : "Draw 3 red cards", eventNum : 1, probability : 0.5 },
{ _id : 3, type : "card", experimentId :"d3rc", description : "Draw 3 red cards", eventNum : 2, probability : 0.49019607843137 },
{ _id : 4, type : "card", experimentId :"d3rc", description : "Draw 3 red cards", eventNum : 3, probability : 0.48 },
{ _id : 5, type : "die", experimentId :"r16", description : "Roll a 1 then a 6", eventNum : 1, probability : 0.16666666666667 },
{ _id : 6, type : "die", experimentId :"r16", description : "Roll a 1 then a 6", eventNum : 2, probability : 0.16666666666667 },
{ _id : 7, type : "card", experimentId :"dak", description : "Draw an ace, then a king", eventNum : 1, probability : 0.07692307692308 },
{ _id : 8, type : "card", experimentId :"dak", description : "Draw an ace, then a king", eventNum : 2, probability : 0.07843137254902 }
] )

Pasos:

  1. Usa $group para agrupar por experimentId y usa $push para crear un arreglo con la probabilidad de cada evento.

  2. Usa $reduce con $multiply para multiplicar y combinar los elementos de probabilityArr en un solo valor y proyéctalo.

db.probability.aggregate(
[
{
$group: {
_id: "$experimentId",
probabilityArr: { $push: "$probability" }
}
},
{
$project: {
description: 1,
results: {
$reduce: {
input: "$probabilityArr",
initialValue: 1,
in: { $multiply: [ "$$value", "$$this" ] }
}
}
}
}
]
)

La operación devuelve lo siguiente:

{ _id : "dak", results : 0.00603318250377101 }
{ _id : "r5", results : 0.16666666666667 }
{ _id : "r16", results : 0.027777777777778886 }
{ _id : "d3rc", results : 0.11764705882352879 }

Una colección llamada clothes contiene los siguientes documentos:

db.clothes.insertMany( [
{ _id : 1, productId : "ts1", description : "T-Shirt", color : "black", size : "M", price : 20, discounts : [ 0.5, 0.1 ] },
{ _id : 2, productId : "j1", description : "Jeans", color : "blue", size : "36", price : 40, discounts : [ 0.25, 0.15, 0.05 ] },
{ _id : 3, productId : "s1", description : "Shorts", color : "beige", size : "32", price : 30, discounts : [ 0.15, 0.05 ] },
{ _id : 4, productId : "ts2", description : "Cool T-Shirt", color : "White", size : "L", price : 25, discounts : [ 0.3 ] },
{ _id : 5, productId : "j2", description : "Designer Jeans", color : "blue", size : "30", price : 80, discounts : [ 0.1, 0.25 ] }
] )

Cada documento contiene un arreglo discounts con los cupones de descuento disponibles actualmente para cada artículo. Si cada descuento puede aplicarse al producto una vez, podemos calcular el precio más bajo mediante $reduce para aplicar la siguiente fórmula a cada elemento del arreglo discounts: (1 - descuento) * precio.

db.clothes.aggregate(
[
{
$project: {
discountedPrice: {
$reduce: {
input: "$discounts",
initialValue: "$price",
in: { $multiply: [ "$$value", { $subtract: [ 1, "$$this" ] } ] }
}
}
}
}
]
)

La operación devuelve lo siguiente:

{ _id : ObjectId("57c893067054e6e47674ce01"), discountedPrice : 9 }
{ _id : ObjectId("57c9932b7054e6e47674ce12"), discountedPrice : 24.224999999999998 }
{ _id : ObjectId("57c993457054e6e47674ce13"), discountedPrice : 24.224999999999998 }
{ _id : ObjectId("57c993687054e6e47674ce14"), discountedPrice : 17.5 }
{ _id : ObjectId("57c993837054e6e47674ce15"), discountedPrice : 54 }

Una colección llamada people contiene los siguientes documentos:

db.people.insertMany( [
{ _id : 1, name : "Melissa", hobbies : [ "softball", "drawing", "reading" ] },
{ _id : 2, name : "Brad", hobbies : [ "gaming", "skateboarding" ] },
{ _id : 3, name : "Scott", hobbies : [ "basketball", "music", "fishing" ] },
{ _id : 4, name : "Tracey", hobbies : [ "acting", "yoga" ] },
{ _id : 5, name : "Josh", hobbies : [ "programming" ] },
{ _id : 6, name : "Claire" }
] )

En el siguiente ejemplo, se reduce el arreglo hobbies de strings en un solo string bio:

db.people.aggregate(
[
// Filter to return only non-empty arrays
{ $match: { "hobbies": { $gt: [ ] } } },
{
$project: {
name: 1,
bio: {
$reduce: {
input: "$hobbies",
initialValue: "My hobbies include:",
in: {
$concat: [
"$$value",
{
$cond: {
if: { $eq: [ "$$value", "My hobbies include:" ] },
then: " ",
else: ", "
}
},
"$$this"
]
}
}
}
}
}
]
)

La operación devuelve lo siguiente:

{ _id : 1, name : "Melissa", bio : "My hobbies include: softball, drawing, reading" }
{ _id : 2, name : "Brad", bio : "My hobbies include: gaming, skateboarding" }
{ _id : 3, name : "Scott", bio : "My hobbies include: basketball, music, fishing" }
{ _id : 4, name : "Tracey", bio : "My hobbies include: acting, yoga" }
{ _id : 5, name : "Josh", bio : "My hobbies include: programming" }

Una colección llamada matrices contiene los siguientes documentos:

db.matrices.insertMany( [
{ _id : 1, arr : [ [ 24, 55, 79 ], [ 14, 78, 35 ], [ 84, 90, 3 ], [ 50, 89, 70 ] ] },
{ _id : 2, arr : [ [ 39, 32, 43, 7 ], [ 62, 17, 80, 64 ], [ 17, 88, 11, 73 ] ] },
{ _id : 3, arr : [ [ 42 ], [ 26, 59 ], [ 17 ], [ 72, 19, 35 ] ] },
{ _id : 4 }
] )

En el siguiente ejemplo, se contraen los arreglos bidimensionales en un solo arreglo collapsed:

db.arrayconcat.aggregate(
[
{
$project: {
collapsed: {
$reduce: {
input: "$arr",
initialValue: [ ],
in: { $concatArrays: [ "$$value", "$$this" ] }
}
}
}
}
]
)

La operación devuelve lo siguiente:

{ _id : 1, collapsed : [ 24, 55, 79, 14, 78, 35, 84, 90, 3, 50, 89, 70 ] }
{ _id : 2, collapsed : [ 39, 32, 43, 7, 62, 17, 80, 64, 17, 88, 11, 73 ] }
{ _id : 3, collapsed : [ 42, 26, 59, 17, 72, 19, 35 ] }
{ _id : 4, collapsed : null }

En el siguiente ejemplo, se realiza la misma contracción del arreglo bidimensional que en el ejemplo anterior, pero también se crea un nuevo arreglo que contiene solo el primer elemento de cada arreglo.

db.arrayconcat.aggregate(
[
{
$project: {
results: {
$reduce: {
input: "$arr",
initialValue: [ ],
in: {
collapsed: {
$concatArrays: [ "$$value.collapsed", "$$this" ]
},
firstValues: {
$concatArrays: [ "$$value.firstValues", { $slice: [ "$$this", 1 ] } ]
}
}
}
}
}
}
]
)

La operación devuelve lo siguiente:

{ _id : 1, results : { collapsed : [ 24, 55, 79, 14, 78, 35, 84, 90, 3, 50, 89, 70 ], firstValues : [ 24, 14, 84, 50 ] } }
{ _id : 2, results : { collapsed : [ 39, 32, 43, 7, 62, 17, 80, 64, 17, 88, 11, 73 ], firstValues : [ 39, 62, 17 ] } }
{ _id : 3, results : { collapsed : [ 42, 26, 59, 17, 72, 19, 35 ], firstValues : [ 42, 26, 17, 72 ] } }
{ _id : 4, results : null }

Crea una colección de muestra llamada people con estos document:

db.people.insertMany( [
{ _id: 1, name: "Melissa", hobbies: [ "softball", "drawing", "reading" ] },
{ _id: 2, name: "Brad", hobbies: [ "gaming", "skateboarding" ] },
{ _id: 3, name: "Scott", hobbies: [ "basketball", "music", "fishing" ] },
{ _id: 4, name: "Tracey", hobbies: [ "acting", "yoga" ] },
{ _id: 5, name: "Josh", hobbies: [ "programming" ] },
{ _id: 6, name: "Claire" }
] )

El campo hobbies contiene un arreglo con los pasatiempos de cada persona en orden de clasificación. El primer hobby en el arreglo es el hobby principal de la persona al que le dedica más tiempo. El primer pasatiempo tiene un índice de arreglo de 0.

El siguiente ejemplo utiliza valueAs, as y arrayIndexAs. La variable myIndex tiene el índice de cada pasatiempo en el arreglo hobbies. El ejemplo devuelve documentos con estos campos:

  • Nombre de la persona.

  • text campo, que incluye el nombre del pasatiempo y la posición de cada pasatiempo en la lista.

db.people.aggregate( [
{
$project: {
_id: 0,
name: 1,
text: {
$reduce: {
input: "$hobbies",
initialValue: "My hobbies include:",
valueAs: "accumulatedText",
as: "hobby",
arrayIndexAs: "myIndex",
in: {
$concat: [
"$$accumulatedText",
" ",
{ $toString: { $add: [ "$$myIndex", 1 ] } },
") ",
"$$hobby"
]
}
}
}
}
}
] )

Salida:

[
{ "name" : "Melissa", "text" : "My hobbies include: 1) softball 2) drawing 3) reading" }
{ "name" : "Brad", "text" : "My hobbies include: 1) gaming 2) skateboarding" }
{ "name" : "Scott", "text" : "My hobbies include: 1) basketball 2) music 3) fishing" }
{ "name" : "Tracey", "text" : "My hobbies include: 1) acting 2) yoga" }
{ "name" : "Josh", "text" : "My hobbies include: 1) programming" }
{ "name" : "Claire", "text" : null }
]

La $$IDX variable devuelve el índice del elemento actual en el arreglo input. Puede usar $$IDX si omite el campo arrayIndexAs de la expresión.

El siguiente ejemplo devuelve los mismos **documents** que el ejemplo de la sección **anterior** Acceder al **índice** de cada elemento de un **arreglo**, pero utiliza $$IDX en lugar de arrayIndexAs:

db.people.aggregate( [
{
$project: {
_id: 0,
name: 1,
text: {
$reduce: {
input: "$hobbies",
initialValue: "My hobbies include:",
valueAs: "accumulatedText",
as: "hobby",
in: {
$concat: [
"$$accumulatedText",
" ",
{ $toString: { $add: [ "$$IDX", 1 ] } },
") ",
"$$hobby"
]
}
}
}
}
}
] )

Volver

$rank

En esta página