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

MongoDB :comment renommer un champ à l'aide de regex

Il ne s'agit pas d'une opération mapReduce, sauf si vous souhaitez une nouvelle collection composée uniquement de _id et value champs qui sont produits à partir de la sortie mapReduce, un peu comme :

    "_id": ObjectId("53f2b954b55e91756c81d3a5"), 
    "value": { 
        "domain": "example.com",
        ... 
    } 
}

Ce qui est au mieux une sorte de remaniement "côté serveur" de votre collection, mais bien sûr pas dans la structure que vous souhaitez.

Bien qu'il existe des moyens d'exécuter tout le code sur le serveur, n'essayez pas de le faire à moins que vous ne soyez vraiment dans un endroit. De toute façon, ces méthodes ne fonctionnent généralement pas bien avec le sharding, qui est généralement là où les gens "sont vraiment dans un endroit" pour la taille des enregistrements.

Lorsque vous souhaitez modifier des choses et le faire en masse, vous devez généralement "boucler" les résultats de la collecte et traiter les mises à jour tout en ayant accès aux informations actuelles du document. Autrement dit, dans le cas où votre "mise à jour" est "basée sur" des informations déjà contenues dans les champs ou la structure du document.

Il n'y a donc pas d'opération "regex replace" disponible, et il n'y en a certainement pas pour renommer un champ. Bouclez donc avec les opérations en masse pour la forme "la plus sûre" de le faire sans exécuter le code sur le serveur.

var bulk = db.collection.initializeOrderedBulkOp();
var counter = 0;

db.collection.find().forEach(function(doc) {

    for ( var k in doc ) {
        if ( doc[k].match(/^2014.*/) ) {
            var update = {};
            update["$unset"][k] = 1;
            update["$set"][ k.replace(/(\d+)-(\d+)-(\d+).+/,"$1$2$3") ] = doc[k];
            bulk.find({ "_id": doc._id }).updateOne(update);
            counter++;
        }
    }

    if ( counter % 1000 == 0 ) {
        bulk.execute();
        bulk = db.collection.initializeOrderedBulkOp();
    }

});

if ( counter % 1000 != 0 )
    bulk.execute();

Donc, les choses principales sont le $unset opérateur pour supprimer le champ existant et le $set opérateur pour créer le nouveau champ dans le document. Vous avez besoin que le contenu du document examine et utilise à la fois le "nom du champ" et la "valeur", d'où la boucle car il n'y a pas d'autre moyen.

Si vous n'avez pas MongoDB 2.6 ou une version ultérieure sur le serveur, le concept de boucle reste toujours sans l'avantage immédiat en termes de performances. Vous pouvez regarder dans des choses comme .eval() afin de traiter sur le serveur, mais comme le suggère la documentation, ce n'est vraiment pas recommandé. À utiliser avec prudence si nécessaire.