MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Le moyen le plus efficace de changer une valeur de champ de chaîne en sa sous-chaîne

Le moyen le plus efficace de le faire est dans la prochaine version de MongoDB au moment de la rédaction de cet article en utilisant le $split opérateur pour diviser notre chaîne comme montré ici puis affectez le dernier élément du tableau à une variable à l'aide du $let opérateur variable et $arrayElemAt les opérateurs.

Ensuite, nous utilisons le $switch opérateur pour effectuer un traitement de condition logique ou une déclaration de cas sur cette variable.

La condition ici est $gt qui renvoie true si la valeur contient "test" , et auquel cas dans le in expression nous divisons cette chaîne et renvoyons simplement le $concat valeur spécifiée du premier élément dans le tableau nouvellement calculé et le - . Si la condition est fausse, nous renvoyons simplement la variable.

Bien sûr, dans notre déclaration de cas, nous utilisons le $indexOfCP qui renvoie -1 s'il n'y avait aucune occurrence de "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 requête d'agrégation produit quelque chose comme ceci :

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

Comme vous pouvez le voir, les données du champ "version" sont des chaînes. Si le type de données pour ce champ n'a pas d'importance, vous pouvez simplement utiliser le $out Opérateur d'étape de pipeline d'agrégation pour écrire le résultat dans une nouvelle collection ou remplacer votre collection.

{ "out": "collection" }

Si vous avez besoin de convertir vos données en nombre à virgule flottante, la seule façon de le faire, simplement parce que MongoDB ne fournit pas un moyen de faire une conversion de type prête à l'emploi, sauf pour un entier en chaîne, est d'itérer l'agrégation Cursor objet et convertissez votre valeur en utilisant parseFloat ou Number puis mettez à jour vos documents en utilisant le $set et l'opérateur bulkWrite() méthode pour une efficacité maximale.

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

Alors que la requête d'agrégation fonctionnera parfaitement dans MongoDB 3.4 ou plus récent, notre meilleur pari à partir de MongoDB 3.2 vers l'arrière est mapReduce avec le bulkWrite() méthode.

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 ressemble à ceci :

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

À partir de là, vous utilisez le précédent .forEach boucle pour mettre à jour vos documents.

De MongoDB 2.6 à 3.0, vous devrez utiliser le Bulk() API et méthode associée comme indiqué dans ma réponse ici.