Comincerebbe con ottenere un elenco distinto di tutte le chiavi della raccolta, utilizzare quelle chiavi come base della query e eseguire un aggiornamento collettivo ordinato utilizzando le operazioni dell'API di massa. La dichiarazione di aggiornamento utilizza l'operatore $unset
per rimuovere i campi.
Il meccanismo per ottenere l'elenco delle chiavi distinte che è necessario assemblare la query è possibile tramite Map-Reduce
. La seguente operazione MapReduce compilerà una raccolta separata con tutti i tasti come i valori _id:
mr = db.runCommand({
"mapreduce": "my_collection",
"map" : function() {
for (var key in this) { emit(key, null); }
},
"reduce" : function(key, stuff) { return null; },
"out": "my_collection" + "_keys"
})
per ottenere un elenco di tutti i tasti dinamici, eseguire distinti sulla raccolta risultante:
db[mr.result].distinct("_id")
// prints ["_id", "year", "year_comment", ...]
Ora dato l'elenco sopra, è possibile assemblare la query creando un oggetto che avrà le sue proprietà impostate all'interno di un ciclo. Normalmente la query avrà questa struttura:
var keysList = ["_id", "year", "year_comment"];
var query = keysList.reduce(function(obj, k) {
var q = {};
q[k] = "";
obj["$or"].push(q);
return obj;
}, { "$or": [] });
printjson(query); // prints {"$or":[{"_id":""},{"year":""},{"year_comment":""}]}
È possibile quindi utilizzare il Bulk API
(disponibile con MongoDB 2.6 e superiore) come un modo di razionalizzare gli aggiornamenti per migliorare le prestazioni con la query di cui sopra. In generale, si dovrebbe essere in grado di avere qualcosa a lavorare come:
var bulk = db.collection.initializeOrderedBulkOp(),
counter = 0,
query = {"$or":[{"_id":""},{"year":""},{"year_comment":""}]},
keysList = ["_id", "year", "year_comment"];
db.collection.find(query).forEach(function(doc){
var emptyKeys = keysList.filter(function(k) { // use filter to return an array of keys which have empty strings
return doc[k]==="";
}),
update = emptyKeys.reduce(function(obj, k) { // set the update object
obj[k] = "";
return obj;
}, { });
bulk.find({ "_id": doc._id }).updateOne({
"$unset": update // use the $unset operator to remove the fields
});
counter++;
if (counter % 1000 == 0) {
// Execute per 1000 operations and re-initialize every 1000 update statements
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp();
}
})
Elimina solo gli elementi vuoti dalla prima riga, ma l'altro lasciato in essi sono luoghi. Sto ancora cercando di scoprire qual è il problema. La shell scrive questo: [oggetto oggetto], [oggetto oggetto], [oggetto oggetto] ... –
Funziona con questa funzione: stampa (tojson (risultato)); Problema risolto. –
@FerencStraub Lo snippet di codice sopra riportato funziona con stripping dei campi del valore nullo nel risultato –