sql >> Database >  >> NoSQL >> MongoDB

MongoDB:een veld hernoemen met regex

Dit is geen mapReduce-bewerking, tenzij u een nieuwe verzameling wilt die alleen uit de _id bestaat en value velden die worden geproduceerd uit de uitvoer van mapReduce, ongeveer zoals:

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

Wat in het beste geval een soort "server-side" bewerking van je verzameling is, maar natuurlijk niet in de structuur die je wilt.

Hoewel er manieren zijn om alle code op de server uit te voeren, probeer dit alsjeblieft niet te doen, tenzij je echt op een plek bent. Deze manieren passen over het algemeen sowieso niet goed bij sharding, wat meestal is waar mensen "echt op hun plek zitten" vanwege de enorme omvang van de records.

Als u dingen wilt wijzigen en dit in bulk wilt doen, moet u over het algemeen de collectieresultaten "doorlopen" en de updates verwerken terwijl u toegang hebt tot de huidige documentinformatie. Dat wil zeggen, in het geval dat uw "update" is "gebaseerd op" informatie die al in velden of de structuur van het document staat.

Er is daarom geen "regex-vervang"-bewerking beschikbaar, en er is er zeker geen voor het hernoemen van een veld. Dus laten we herhalen met bulkbewerkingen voor de "veiligste" vorm om dit te doen zonder de code allemaal op de server uit te voeren.

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

Dus de belangrijkste dingen daar zijn de $unset operator om het bestaande veld en de $set operator om het nieuwe veld in het document te maken. U hebt de documentinhoud nodig om zowel de "veldnaam" als de "waarde" te onderzoeken en te gebruiken, dus vandaar de lus omdat er geen andere manier is.

Als je MongoDB 2.6 of hoger niet op de server hebt, blijft het looping-concept bestaan ​​zonder het onmiddellijke prestatievoordeel. Je kunt dingen bekijken als .eval() om op de server te verwerken, maar zoals de documentatie suggereert, wordt het echt niet aanbevolen. Wees voorzichtig als het moet.



  1. Een typetoewijzing afdwingen met mgo

  2. Kunnen rails-scopes filteren op het aantal geassocieerde klassen voor een bepaald veld?

  3. Mongodb - slechte zoekopdracht:BadValue onbekende operator op het hoogste niveau:$gte

  4. SignalR schalen met Azure Worker Role en OWIN