Con MongoDB 4.2 y posteriores, el método de actualización ahora puede tomar un documento o una canalización agregada donde se pueden utilizar las siguientes etapas:
$addFields
y su alias$set
$project
y su alias$unset
$replaceRoot
y su alias$replaceWith
.
Armado con lo anterior, su operación de actualización con la canalización agregada será anular las tags
campo concatenando un tags
filtrado matriz y una matriz asignada de la lista de entrada con alguna búsqueda de datos en el mapa:
Para empezar, la expresión agregada que filtra la matriz de etiquetas usa el $filter
y sigue:
const myTags = ["architecture", "blabladontexist"];
{
"$filter": {
"input": "$tags",
"cond": {
"$not": [
{ "$in": ["$$this.t", myTags] }
]
}
}
}
que produce la matriz filtrada de documentos
[
{ "t" : "contemporary", "n" : 2 },
{ "t" : "creative", "n" : 1 },
{ "t" : "concrete", "n" : 3 }
]
Ahora la segunda parte será derivar la otra matriz que se concatenará a la anterior. Esta matriz requiere un $map
sobre myTags
matriz de entrada como
{
"$map": {
"input": myTags,
"in": {
"$cond": {
"if": { "$in": ["$$this", "$tags.t"] },
"then": {
"t": "$$this",
"n": {
"$sum": [
{
"$arrayElemAt": [
"$tags.n",
{ "$indexOfArray": [ "$tags.t", "$$this" ] }
]
},
1
]
}
},
"else": { "t": "$$this", "n": 0 }
}
}
}
}
Lo anterior $map
esencialmente recorre la matriz de entrada y verifica con cada elemento si está en las tags
matriz que compara el t
propiedad, si existe, entonces el valor de n
el campo del subdocumento se convierte en su n
actual valor expresado con
{
"$arrayElemAt": [
"$tags.n",
{ "$indexOfArray": [ "$tags.t", "$$this" ] }
]
}
de lo contrario, agregue el documento predeterminado con un valor n de 0.
En general, su operación de actualización será la siguiente
Su operación de actualización final se convierte en:
const myTags = ["architecture", "blabladontexist"];
db.getCollection('coll').update(
{ "_id": "1234" },
[
{ "$set": {
"tags": {
"$concatArrays": [
{ "$filter": {
"input": "$tags",
"cond": { "$not": [ { "$in": ["$$this.t", myTags] } ] }
} },
{ "$map": {
"input": myTags,
"in": {
"$cond": [
{ "$in": ["$$this", "$tags.t"] },
{ "t": "$$this", "n": {
"$sum": [
{ "$arrayElemAt": [
"$tags.n",
{ "$indexOfArray": [ "$tags.t", "$$this" ] }
] },
1
]
} },
{ "t": "$$this", "n": 0 }
]
}
} }
]
}
} }
],
{ "upsert": true }
);