Não podemos usar o
$type
operador para filtrar nossos documentos aqui porque o tipo dos elementos em nosso array é "string" e conforme mencionado na documentação:Mas felizmente o MongoDB também fornece o
$exists
operador que pode ser usado aqui com um índice de matriz numérica. Agora, como podemos atualizar esses documentos?
Bem, da versão MongoDB <=3.2, a única opção que temos é
mapReduce()
mas primeiro vamos ver a outra alternativa na próxima versão do MongoDB. A partir do MongoDB 3.4, podemos
$project
nossos documentos e use o $split
operador para dividir nossa string em uma matriz de substrings. Observe que para dividir apenas as "tags" que são string, precisamos de um lógico
$cond
processamento de ção para dividir apenas os valores que são string. A condição aqui é $eq
que avaliam como true
quando o $type
do campo é igual a "string"
. A propósito $type
aqui é novo em 3.4. Finalmente, podemos substituir a coleção antiga usando o
$out
operador de estágio de pipeline. Mas precisamos especificar explicitamente a inclusão de outro campo no $project
estágio . db.collection.aggregate(
[
{ "$project": {
"tags": {
"$cond": [
{ "$eq": [
{ "$type": "$tags" },
"string"
]},
{ "$split": [ "$tags", " " ] },
"$tags"
]
}
}},
{ "$out": "collection" }
]
)
Com
mapReduce
, precisamos usar a matriz Array.prototype.split()
para emitir o array de substrings em nossa função map . Também precisamos filtrar nossos documentos usando a opção "query". A partir daí, precisaremos iterar o array "results" e $set
o novo valor para "tags" usando operações em massa usando o bulkWrite()
método novo na versão 3.2 ou o agora obsoleto Bulk()
se estivermos na versão 2.6 ou 3.0, conforme mostrado aqui.
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']