Non possiamo utilizzare $type
operatore per filtrare i nostri documenti qui perché il tipo degli elementi nel nostro array è "string" e come menzionato nella documentazione:
Ma fortunatamente MongoDB fornisce anche $exists
operatore che può essere utilizzato qui con un indice di matrice numerico.
Ora come possiamo aggiornare quei documenti?
Bene, dalla versione MongoDB <=3.2, l'unica opzione che abbiamo è mapReduce()
ma prima diamo un'occhiata all'altra alternativa nella prossima versione di MongoDB.
A partire da MongoDB 3.4, possiamo $project
i nostri documenti e usa il $split
per dividere la nostra stringa in un array di sottostringhe.
Nota che per dividere solo quei "tag" che sono string, abbiamo bisogno di un logico $cond
elaborazione ition per dividere solo i valori che sono string. La condizione qui è $eq
che restituisce true
quando il $type
del campo è uguale a "string"
. A proposito $type
ecco una novità in 3.4.
Infine possiamo sovrascrivere la vecchia raccolta utilizzando $out
operatore della fase del gasdotto. Ma dobbiamo specificare esplicitamente l'inclusione di altri campi nel $project
fase .
db.collection.aggregate(
[
{ "$project": {
"tags": {
"$cond": [
{ "$eq": [
{ "$type": "$tags" },
"string"
]},
{ "$split": [ "$tags", " " ] },
"$tags"
]
}
}},
{ "$out": "collection" }
]
)
Con mapReduce
, dobbiamo utilizzare l' Array.prototype.split()
per emettere l'array di sottostringhe nella nostra funzione mappa . Abbiamo anche bisogno di filtrare i nostri documenti usando l'opzione "query". Da lì dovremo iterare l'array "results" e $set
il nuovo valore per i "tag" utilizzando operazioni in blocco utilizzando bulkWrite()
metodo nuovo in 3.2 o l'ormai deprecato Bulk()
se siamo su 2.6 o 3.0 come mostrato qui.
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']