MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Il modo più efficiente per modificare il valore di un campo stringa nella sua sottostringa

Il modo più efficiente per farlo è nella prossima versione di MongoDB al momento della stesura di questo articolo utilizzando $split operatore per dividere la nostra stringa come mostrato qui quindi assegna l'ultimo elemento dell'array a una variabile utilizzando $let operatore variabile e $arrayElemAt operatori.

Successivamente, utilizziamo il $switch operatore per eseguire un'elaborazione di una condizione logica o un'istruzione case rispetto a quella variabile.

La condizione qui è $gt che restituisce true se il valore contiene "test" , e in tal caso in in espressione dividiamo quella stringa e restituiamo semplicemente $concat valore enato del primo elemento nell'array appena calcolato e il - . Se la condizione restituisce false, restituiamo semplicemente la variabile.

Ovviamente nella nostra istruzione case, utilizziamo il $indexOfCP che restituisce -1 se non ci sono occorrenze di "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" 
                        }
                    }
                }
            }
        }}
    ]
)

La query di aggregazione produce qualcosa del genere:

{ "_id" : ObjectId("57a98773cbbd42a2156260d8"), "data" : 11, "version" : "32" }
{ "_id" : ObjectId("57a98773cbbd42a2156260d9"), "data" : 55, "version" : "-42" }

Come puoi vedere, i dati del campo "versione" sono stringa. Se il tipo di dati per quel campo non ha importanza, puoi semplicemente usare $out operatore della fase della pipeline di aggregazione per scrivere il risultato in una nuova raccolta o sostituire la raccolta.

{ "out": "collection" }

Se hai bisogno di convertire i tuoi dati in un numero in virgola mobile, l'unico modo per farlo, semplicemente perché MongoDB non fornisce un modo per eseguire la conversione del tipo fuori dagli schemi tranne che da intero a stringa, è iterare il cursore di aggregazione oggetto e converti il ​​tuo valore utilizzando parseFloat o Number quindi aggiorna i tuoi documenti utilizzando $set operatore e bulkWrite() metodo per la massima efficienza.

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);
}

Sebbene la query di aggregazione funzioni perfettamente in MongoDB 3.4 o versioni successive, la soluzione migliore da MongoDB 3.2 al contrario è mapReduce con bulkWrite() metodo.

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 assomiglia a questo:

[
    {
        "_id" : ObjectId("57a98773cbbd42a2156260d8"),
        "value" : "32"
    },
    {
        "_id" : ObjectId("57a98773cbbd42a2156260d9"),
        "value" : "-42"
    }
]

Da qui usi il precedente .forEach loop per aggiornare i tuoi documenti.

Da MongoDB 2.6 a 3.0 sarà necessario utilizzare il deprecato Bulk() API e metodo associato come mostrato nella mia risposta qui.