Docs Menu
Docs Home
/ /
Etapas de la pipeline de agregación

$replaceWith (agregación)

$replaceWith

Reemplaza el documento de entrada por el documento especificado. Esta operación reemplaza todos los campos existentes en el documento de entrada, incluido el _id campo. Con, puede promover un documento incrustado al nivel superior. También puede especificar un nuevo documento como $replaceWith reemplazo.

La etapa realiza la misma acción que $replaceWith la $replaceRoot etapa, pero las etapas tienen diferentes formas.

La etapa $replaceWith tiene el siguiente formato:

{ $replaceWith: <replacementDocument> }

El documento de reemplazo puede ser cualquier expresión válida que se resuelva en un documento. Para obtener más información sobre las expresiones, consulta Expresiones.

Si el <replacementDocument> no es un documento, $replaceWith produce errores y falla.

Si el <replacementDocument> se resuelve en un documento inexistente (es decir, el documento no existe), $replaceWith genera un error y falla. Por ejemplo, crea una colección con los siguientes documentos:

db.collection.insertMany([
{ "_id": 1, "name" : { "first" : "John", "last" : "Backus" } },
{ "_id": 2, "name" : { "first" : "John", "last" : "McCarthy" } },
{ "_id": 3, "name": { "first" : "Grace", "last" : "Hopper" } },
{ "_id": 4, "firstname": "Ole-Johan", "lastname" : "Dahl" },
])

Entonces, la siguiente operación falla porque uno de los documentos no tiene $replaceWith el name campo:

db.collection.aggregate([
{ $replaceWith: "$name" }
])

Para evitar el error, puede utilizar para fusionar $mergeObjects el name documento con algún documento predeterminado; por ejemplo:

db.collection.aggregate([
{ $replaceWith: { $mergeObjects: [ { _id: "$_id", first: "", last: "" }, "$name" ] } }
])

Alternativamente, puede omitir los documentos que no tienen el campo name incluyendo una etapa $match para verificar la existencia del campo del documento antes de pasar los documentos a la etapa $replaceWith:

db.collection.aggregate([
{ $match: { name : { $exists: true, $not: { $type: "array" }, $type: "object" } } },
{ $replaceWith: "$name" }
])

O bien, puede usar la expresión $ifNull para especificar algún otro documento como raíz; por ejemplo:

db.collection.aggregate([
{ $replaceWith: { $ifNull: [ "$name", { _id: "$_id", missingName: true} ] } }
])

Cree una colección llamada people con los siguientes documentos:

db.people.insertMany([
{ "_id" : 1, "name" : "Arlene", "age" : 34, "pets" : { "dogs" : 2, "cats" : 1 } },
{ "_id" : 2, "name" : "Sam", "age" : 41, "pets" : { "cats" : 1, "fish" : 3 } },
{ "_id" : 3, "name" : "Maria", "age" : 25 }
])

La siguiente operación utiliza la etapa $replaceWith para reemplazar cada documento de entrada con el resultado de una operación $mergeObjects. La expresión $mergeObjects fusiona el documento por defecto especificado con el documento pets.

db.people.aggregate( [
{ $replaceWith: { $mergeObjects: [ { dogs: 0, cats: 0, birds: 0, fish: 0 }, "$pets" ] } }
] )

La operación devuelve los siguientes resultados:

{ "dogs" : 2, "cats" : 1, "birds" : 0, "fish" : 0 }
{ "dogs" : 0, "cats" : 1, "birds" : 0, "fish" : 3 }
{ "dogs" : 0, "cats" : 0, "birds" : 0, "fish" : 0 }

Una colección llamada students contiene los siguientes documentos:

db.students.insertMany([
{
"_id" : 1,
"grades" : [
{ "test": 1, "grade" : 80, "mean" : 75, "std" : 6 },
{ "test": 2, "grade" : 85, "mean" : 90, "std" : 4 },
{ "test": 3, "grade" : 95, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "test": 1, "grade" : 90, "mean" : 75, "std" : 6 },
{ "test": 2, "grade" : 87, "mean" : 90, "std" : 3 },
{ "test": 3, "grade" : 91, "mean" : 85, "std" : 4 }
]
}
])

La siguiente operación promueve los documentos incrustados con el campo grade que son mayores o iguales a 90 al nivel superior:

db.students.aggregate( [
{ $unwind: "$grades" },
{ $match: { "grades.grade" : { $gte: 90 } } },
{ $replaceWith: "$grades" }
] )

La operación devuelve los siguientes resultados:

{ "test" : 3, "grade" : 95, "mean" : 85, "std" : 6 }
{ "test" : 1, "grade" : 90, "mean" : 75, "std" : 6 }
{ "test" : 3, "grade" : 91, "mean" : 85, "std" : 4 }

Una colección de ejemplo sales se rellena con los siguientes documentos:

db.sales.insertMany([
{ "_id" : 1, "item" : "butter", "price" : 10, "quantity": 2, date: ISODate("2019-03-01T08:00:00Z"), status: "C" },
{ "_id" : 2, "item" : "cream", "price" : 20, "quantity": 1, date: ISODate("2019-03-01T09:00:00Z"), status: "A" },
{ "_id" : 3, "item" : "jam", "price" : 5, "quantity": 10, date: ISODate("2019-03-15T09:00:00Z"), status: "C" },
{ "_id" : 4, "item" : "muffins", "price" : 5, "quantity": 10, date: ISODate("2019-03-15T09:00:00Z"), status: "C" }
])

Supongamos que, para fines de informes, desea calcular el importe total de cada venta completada al momento de la ejecución del informe. La siguiente operación busca todas las ventas con estado C y crea nuevos documentos utilizando la etapa$replaceWith. La etapa$replaceWithcalcula el importe total y utiliza la variableNOWpara obtener la hora actual.

db.sales.aggregate([
{ $match: { status: "C" } },
{ $replaceWith: { _id: "$_id", item: "$item", amount: { $multiply: [ "$price", "$quantity"]}, status: "Complete", asofDate: "$$NOW" } }
])

La operación devuelve los siguientes documentos:

{ "_id" : 1, "item" : "butter", "amount" : 20, "status" : "Complete", "asofDate" : ISODate("2019-06-03T22:47:54.812Z") }
{ "_id" : 3, "item" : "jam", "amount" : 50, "status" : "Complete", "asofDate" : ISODate("2019-06-03T22:47:54.812Z") }
{ "_id" : 4, "item" : "muffins", "amount" : 50, "status" : "Complete", "asofDate" : ISODate("2019-06-03T22:47:54.812Z") }

Se completa una colección de ejemplo reportedsales con la información de ventas reportada por trimestre y regiones:

db.reportedsales.insertMany( [
{ _id: 1, quarter: "2019Q1", region: "A", qty: 400 },
{ _id: 2, quarter: "2019Q1", region: "B", qty: 550 },
{ _id: 3, quarter: "2019Q1", region: "C", qty: 1000 },
{ _id: 4, quarter: "2019Q2", region: "A", qty: 660 },
{ _id: 5, quarter: "2019Q2", region: "B", qty: 500 },
{ _id: 6, quarter: "2019Q2", region: "C", qty: 1200 }
] )

Supongamos que para fines de informes, desea ver los datos de ventas informados por trimestre; por ejemplo:

{ "_id" : "2019Q1", "A" : 400, "B" : 550, "C" : 1000 }

Para ver los datos agrupados por trimestre, puede utilizar la siguiente secuencia de agregación:

db.reportedsales.aggregate( [
{ $addFields: { obj: { k: "$region", v: "$qty" } } },
{ $group: { _id: "$quarter", items: { $push: "$obj" } } },
{ $project: { items2: { $concatArrays: [ [ { "k": "_id", "v": "$_id" } ], "$items" ] } } },
{ $replaceWith: { $arrayToObject: "$items2" } }
] )
Primera etapa:

La etapa añade un $addFields nuevo obj campo de documento que define la clave k como el valor de la región y el valor v como la cantidad de dicha región. Por ejemplo:

{ "_id" : 1, "quarter" : "2019Q1", "region" : "A", "qty" : 400, "obj" : { "k" : "A", "v" : 400 } }
Segunda fase:

La etapa$groupagrupa por trimestre y utiliza$pushpara acumular los campos obj en un nuevo campo de matriz items. Por ejemplo:

{ "_id" : "2019Q1", "items" : [ { "k" : "A", "v" : 400 }, { "k" : "B", "v" : 550 }, { "k" : "C", "v" : 1000 } ] }
Tercera etapa:

La etapa $project utiliza $concatArrays para crear un nuevo arreglo items2 que incluye la información _id y los elementos del arreglo items:

{ "_id" : "2019Q1", "items2" : [ { "k" : "_id", "v" : "2019Q1" }, { "k" : "A", "v" : 400 }, { "k" : "B", "v" : 550 }, { "k" : "C", "v" : 1000 } ] }
Cuarta etapa:

El $replaceWith usa el para convertir $arrayToObject el items2 en un documento, utilizando los k pares de clave y valor especificados,v y envía ese documento a la siguiente etapa. Por ejemplo:

{ "_id" : "2019Q1", "A" : 400, "B" : 550, "C" : 1000 }

La agregación devuelve el siguiente documento:

{ "_id" : "2019Q1", "A" : 400, "B" : 550, "C" : 1000 }
{ "_id" : "2019Q2", "A" : 660, "B" : 500, "C" : 1200 }

Cree una colección llamada contacts con los siguientes documentos:

db.contacts.insertMany( [
{ "_id" : 1, name: "Fred", email: "fred@example.net" },
{ "_id" : 2, name: "Frank N. Stine", cell: "012-345-9999" },
{ "_id" : 3, name: "Gren Dell", cell: "987-654-3210", email: "beo@example.net" }
] )

La siguiente operación utiliza $replaceWith junto con $mergeObjects para generar los documentos actuales con valores por defecto para los campos faltantes:

db.contacts.aggregate( [
{ $replaceWith:
{ $mergeObjects:
[
{ _id: "", name: "", email: "", cell: "", home: "" },
"$$ROOT"
]
}
}
] )

La agregación devuelve los siguientes documentos:

{
_id: 1,
name: 'Fred',
email: 'fred@example.net',
cell: '',
home: ''
},
{
_id: 2,
name: 'Frank N. Stine',
email: '',
cell: '012-345-9999',
home: ''
},
{
_id: 3,
name: 'Gren Dell',
email: 'beo@example.net',
cell: '',
home: '987-654-3210'
}

Volver

$replaceRoot

En esta página