Der effizienteste Weg, dies zu tun, ist in der bevorstehenden Veröffentlichung von MongoDB zum Zeitpunkt des Schreibens der $split
Operator unsere String aufgeteilt als shown here dann auf eine Variable mit dem $let
Variable Operator das letzte Element in dem Array zuweisen und die $arrayElemAt
Betreiber.
Als nächstes verwenden wir den Operator $switch
, um eine logische Bedingungsverarbeitung oder case-Anweisung für diese Variable auszuführen.
Die Bedingung ist hier $gt
die true zurück, wenn der Wert "test"
enthält, und in dem Fall, in der in Expression teilten wir die Zeichenfolge einfach und geben den $concat
enated Wert des ersten Elements in der neu berechneten Array und die -
. Wenn die Bedingung false ergibt, geben wir nur die Variable zurück.
Natürlich verwenden wir in unserem Fall die $indexOfCP
, die -1
zurückgibt, wenn keine "test"
aufgetreten ist.
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 Aggregation Abfrage ergibt dies so etwas wie:
{ "_id" : ObjectId("57a98773cbbd42a2156260d8"), "data" : 11, "version" : "32" }
{ "_id" : ObjectId("57a98773cbbd42a2156260d9"), "data" : 55, "version" : "-42" }
Wie Sie sehen können, die "Version" Felddatenfolge sind. Wenn der Datentyp für dieses Feld dann keine Rolle spielt, können Sie einfach den Aggregationspipelinestufenoperatorverwenden, um das Ergebnis in eine neue Sammlung zu schreiben oder Ihre Sammlung zu ersetzen.
{ "out": "collection" }
Wenn Sie dann Ihre Daten in Fließkommazahl konvertieren, ist der einzige Weg, dies zu tun, einfach weil MongoDB nicht keine Möglichkeit bietet Typumwandlung aus der Box mit Ausnahme integer zu bespannen zu tun , iterieren Sie das Aggregations-Cursor-Objekt und konvertieren Sie Ihren Wert mit parseFloat
oder Number
und aktualisieren Sie dann Ihre Dokumente mit dem Operator $set
und der 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 Aggregationsanfrage in MongoDB perfekt funktionieren 3.4 oder neuer unsere beste Wette von MongoDB 3.2 rückwärts ist mapReduce
mit dem bulkWrite()
Verfahren.
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"];
results
sieht wie folgt aus:
[
{
"_id" : ObjectId("57a98773cbbd42a2156260d8"),
"value" : "32"
},
{
"_id" : ObjectId("57a98773cbbd42a2156260d9"),
"value" : "-42"
}
]
Von hier können Sie die vorherige .forEach
Schleife benutzen, um Ihre Dokumente zu aktualisieren.
Von MongoDB 2,6 bis 3,0 Sie müssen das jetzt veraltet Bulk()
API verwenden und das zugehörige Verfahren als Show in meinem answer here.
in Bezug auf den Titel, '32' ist __not__ eine Teil von' "0.0. 32 ". In der Tat ist es überhaupt keine Schnur. JFYI. –
Der Kern des Problems besteht darin, einen Teilstring zu nehmen. Könntest du mir helfen, einen besseren Titel zu finden? –