De meest efficiënte manier om dit te doen is in de aankomende release van MongoDB vanaf dit moment van schrijven met behulp van de $split
operator om onze string te splitsen als hier weergegeven
wijs vervolgens het laatste element in de array toe aan een variabele met behulp van de $let
variabele operator en de $arrayElemAt
exploitanten.
Vervolgens gebruiken we de $switch
operator om een logische conditieverwerking of case-statement tegen die variabele uit te voeren.
De voorwaarde hier is $gt
die true retourneert als de waarde "test"
. bevat , en in dat geval in de in expressie splitsen we die string en retourneren we gewoon de $concat
ingevoerde waarde van het eerste element in de nieuw berekende array en de -
. Als de voorwaarde onwaar is, retourneren we de variabele.
Natuurlijk gebruiken we in onze case-statement de $indexOfCP
wat -1
returns retourneert als er geen gevallen waren van "test"
.
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"
}
}
}
}
}}
]
)
De aggregatiequery levert zoiets als dit op:
{ "_id" : ObjectId("57a98773cbbd42a2156260d8"), "data" : 11, "version" : "32" }
{ "_id" : ObjectId("57a98773cbbd42a2156260d9"), "data" : 55, "version" : "-42" }
Zoals u kunt zien, zijn de veldgegevens "versie" een tekenreeks. Als het gegevenstype voor dat veld er dan niet toe doet, kunt u gewoon de $out
. gebruiken aggregatiepijplijnfaseoperator om het resultaat naar een nieuwe verzameling te schrijven of uw verzameling te vervangen.
{ "out": "collection" }
Als u uw gegevens naar een getal met drijvende komma moet converteren, is de enige manier om dit te doen, simpelweg omdat MongoDB geen manier biedt om typeconversie uit de doos te doen, behalve integer naar string, door de aggregatiecursor te herhalen object en converteer uw waarde met parseFloat
of Number
werk vervolgens uw documenten bij met de $set
operator en de bulkWrite()
methode voor maximale efficiëntie.
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);
}
Hoewel de aggregatiequery perfect werkt in MongoDB 3.4 of nieuwer, is onze beste gok vanaf MongoDB 3.2 achteruit mapReduce
met de 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"];
results
ziet er zo uit:
[
{
"_id" : ObjectId("57a98773cbbd42a2156260d8"),
"value" : "32"
},
{
"_id" : ObjectId("57a98773cbbd42a2156260d9"),
"value" : "-42"
}
]
Vanaf hier gebruik je de vorige .forEach
loop om uw documenten bij te werken.
Van MongoDB 2.6 tot 3.0 moet je de nu verouderde Bulk()
API en de bijbehorende methode zoals weergegeven in mijn antwoord hier.