MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Effizienteste Methode, um den Wert eines Zeichenfolgenfelds in seine Teilzeichenfolge zu ändern

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