Der effizienteste Weg, dies zu tun, ist in der kommenden Version von MongoDB zum Zeitpunkt des Schreibens dieses Artikels die Verwendung von $split
-Operator, um unsere Zeichenfolge wie hier gezeigt
aufzuteilen Weisen Sie dann das letzte Element im Array mithilfe von einer Variablen zu $let
Variablenoperator und $arrayElemAt
Betreiber.
Als nächstes verwenden wir den $switch
Operator, um eine logische Bedingungsverarbeitung oder Case-Anweisung für diese Variable auszuführen.
Die Bedingung hier ist $gt
was true zurückgibt, wenn der Wert "test"
enthält , und in diesem Fall im in Ausdruck teilen wir diesen String auf und geben einfach den $concat
enated-Wert des ersten Elements im neu berechneten Array und dem -
. Wenn die Bedingung als falsch ausgewertet wird, geben wir einfach die Variable zurück.
Natürlich verwenden wir in unserer Case-Anweisung den $indexOfCP
was -1
zurückgibt wenn "test"
nicht vorkommt .
let cursor = db.collection.aggregate(
[
{ "$project": {
"data": 1,
"version": {
"$let": {
"vars": {
"v": {
"$arrayElemAt": [
{ "$split": [ "$version", "." ] },
-1
]
}
},
"in": {
"$switch": {
"branches": [
{
"case": {
"$gt": [
{ "$indexOfCP": [ "$$v", "test" ] },
-1
]
},
"then": {
"$concat": [
"-",
"",
{ "$arrayElemAt": [
{ "$split": [ "$$v", "-" ] },
0
]}
]
}
}
],
"default": "$$v"
}
}
}
}
}}
]
)
Die Aggregationsabfrage erzeugt etwa Folgendes:
{ "_id" : ObjectId("57a98773cbbd42a2156260d8"), "data" : 11, "version" : "32" }
{ "_id" : ObjectId("57a98773cbbd42a2156260d9"), "data" : 55, "version" : "-42" }
Wie Sie sehen können, sind die Felddaten "Version" Zeichenfolgen. Wenn der Datentyp für dieses Feld dann keine Rolle spielt, können Sie einfach den $out
verwenden Aggregationspipeline-Stufenoperator, um das Ergebnis in eine neue Sammlung zu schreiben oder Ihre Sammlung zu ersetzen.
{ "out": "collection" }
Wenn Sie Ihre Daten in Gleitkommazahlen konvertieren müssen, besteht die einzige Möglichkeit, den Aggregations-Cursor zu iterieren, einfach deshalb, weil MongoDB keine Möglichkeit zur standardmäßigen Typkonvertierung bietet, mit Ausnahme von Integer in String -Objekt und konvertieren Sie Ihren Wert mit parseFloat
oder Nummer
Aktualisieren Sie dann Ihre Dokumente mit $set
-Operator und bulkWrite()
Methode für maximale Effizienz.
let requests = [];
cursor.forEach(doc => {
requests.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": {
"$set": {
"data": doc.data,
"version": parseFloat(doc.version)
},
"$unset": { "person": " " }
}
}
});
if ( requests.length === 1000 ) {
// Execute per 1000 ops and re-init
db.collection.bulkWrite(requests);
requests = [];
}}
);
// Clean up queues
if(requests.length > 0) {
db.coll.bulkWrite(requests);
}
Während die Aggregationsabfrage in MongoDB 3.4 oder höher perfekt funktioniert, ist unsere beste Wahl von MongoDB 3.2 rückwärts mapReduce
mit dem bulkWrite()
Methode.
var results = db.collection.mapReduce(
function() {
var v = this.version.split(".")[2];
emit(this._id, v.indexOf("-") > -1 ? "-"+v.replace(/\D+/g, '') : v)
},
function(key, value) {},
{ "out": { "inline": 1 } }
)["results"];
Ergebnisse
sieht so aus:
[
{
"_id" : ObjectId("57a98773cbbd42a2156260d8"),
"value" : "32"
},
{
"_id" : ObjectId("57a98773cbbd42a2156260d9"),
"value" : "-42"
}
]
Von hier aus verwenden Sie den vorherigen .forEach
Schleife, um Ihre Dokumente zu aktualisieren.
Von MongoDB 2.6 bis 3.0 müssen Sie den jetzt veralteten Bulk( )
API und die damit verbundene Methode, wie in meiner Antwort hier.
gezeigt