No podemos usar el $type
operador para filtrar nuestros documentos aquí porque el tipo de los elementos en nuestra matriz es "cadena" y como se menciona en la documentación:
Pero, afortunadamente, MongoDB también proporciona el $exists
operador que se puede utilizar aquí con un índice de matriz numérica.
Ahora, ¿cómo podemos actualizar esos documentos?
Bueno, desde MongoDB versión <=3.2, la única opción que tenemos es mapReduce()
pero primero veamos la otra alternativa en el próximo lanzamiento de MongoDB.
A partir de MongoDB 3.4, podemos $project
nuestros documentos y usar el $split
operador para dividir nuestra cadena en una matriz de subcadenas.
Tenga en cuenta que para dividir solo aquellas "etiquetas" que son cadenas, necesitamos un lógico $cond
procesamiento de ition para dividir solo los valores que son cadenas. La condición aquí es $eq
que se evalúan como true
cuando el $type
del campo es igual a "string"
. Por cierto $type
aquí hay algo nuevo en 3.4.
Finalmente, podemos sobrescribir la colección anterior usando $out
operador de etapa de tubería. Pero necesitamos especificar explícitamente la inclusión de otro campo en el $project
escenario .
db.collection.aggregate(
[
{ "$project": {
"tags": {
"$cond": [
{ "$eq": [
{ "$type": "$tags" },
"string"
]},
{ "$split": [ "$tags", " " ] },
"$tags"
]
}
}},
{ "$out": "collection" }
]
)
Con mapReduce
, necesitamos usar el Array.prototype.split()
para emitir la matriz de subcadenas en nuestra función de mapa . También necesitamos filtrar nuestros documentos usando la opción "consultar". A partir de ahí, necesitaremos iterar la matriz de "resultados" y $set
el nuevo valor para "etiquetas" usando operaciones masivas usando el bulkWrite()
método nuevo en 3.2 o el ahora obsoleto Bulk()
si estamos en 2.6 o 3.0 como se muestra aquí.
db.collection.mapReduce(
function() { emit(this._id, this.tags.split(" ")); },
function(key, value) {},
{
"out": { "inline": 1 },
"query": {
"tags.0": { "$exists": false },
"tags": { "$type": 2 }
}
}
)['results']