sql >> Databasteknik >  >> NoSQL >> MongoDB

MongoDB:Hur man byter namn på ett fält med regex

Detta är inte en mapReduce-operation, inte om du inte vill ha en ny samling som endast består av _id och värde fält som produceras från mapReduce output, ungefär som:

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

Vilket i bästa fall är en slags "serverside"-omarbetning av din samling, men naturligtvis inte i den struktur du vill ha.

Även om det finns sätt att exekvera all kod på servern, försök inte göra det om du inte verkligen är på plats. Dessa sätt fungerar i allmänhet inte bra med sharding hur som helst, vilket vanligtvis är där människor "verkligen är på plats" för den stora storleken på rekord.

När du vill ändra saker och göra det i bulk måste du i allmänhet "loopa" insamlingsresultaten och bearbeta uppdateringarna samtidigt som du har tillgång till den aktuella dokumentinformationen. Det vill säga i fallet där din "uppdatering" är "baserad på" information som redan finns i fält eller struktur i dokumentet.

Det finns därför ingen "regex replace"-operation tillgänglig, och det finns absolut ingen för att byta namn på ett fält. Så låt oss gå i en slinga med bulkoperationer för den "säkraste" formen att göra detta utan att köra koden på servern.

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

Så det viktigaste där är $unset operatör för att ta bort det befintliga fältet och $set operatör för att skapa det nya fältet i dokumentet. Du behöver dokumentinnehållet för att undersöka och använda både "fältnamn" och "värde", så därav looping eftersom det inte finns något annat sätt.

Om du inte har MongoDB 2.6 eller senare på servern kvarstår looping-konceptet fortfarande utan den omedelbara prestandafördelen. Du kan titta på saker som .eval() för att bearbeta på servern, men som dokumentationen antyder är det verkligen inte att rekommendera. Använd med försiktighet om du måste.



  1. MongoDB Aggregate - Fråga för att få det senaste objektet i grupp

  2. MongoDB och upsert-problem

  3. Hur konverterar man år och vecka på året som erhållits från MongoDB-frågan till Joda datetime?

  4. Ställa in utgångstid för en samling i mongodb med mongoose