Update MongoDB collection using $toLower

后端 未结 6 1074
盖世英雄少女心
盖世英雄少女心 2020-12-01 05:34

I have an existing MongoDB collection containing user names. The user names contain both lower case and upper case letters.

I want to update all the user names so th

相关标签:
6条回答
  • 2020-12-01 05:42

    Starting Mongo 4.2, db.collection.update() can accept an aggregation pipeline, finally allowing the update of a field based on its own value:

    // { username: "Hello World" }
    db.collection.update(
      {},
      [{ $set: { username: { $toLower: "$username" } } }],
      { multi: true }
    )
    // { username: "hello world" }
    
    • The first part {} is the match query, filtering which documents to update (in this case all documents).

    • The second part [{ $set: { username: { $toLower: "$username" } } }], is the update aggregation pipeline (note the squared brackets signifying the use of an aggregation pipeline):

      • $set is a new aggregation operator which in this case modifies the value for "username".
      • Using $toLower, we modify the value of "username" by its lowercase version.
    • Don't forget { multi: true }, otherwise only the first matching document will be updated.

    0 讨论(0)
  • 2020-12-01 05:42

    Just a note to make sure the field exists for all entries in your collection. If not you will need an if statement, like the following:

    if (e.UserName) e.UserName = e.UserName.toLowerCase();
    
    0 讨论(0)
  • 2020-12-01 05:46

    MongoDB does not have a concept of $toLower as a command. The solution is to run a big for loop over the data and issue the updates individually.

    You can do this in any driver or from the shell:

    db.myCollection.find().forEach(
      function(e) {
        e.UserName = e.UserName.toLowerCase();
        db.myCollection.save(e);
      }
    )
    

    You can also replace the save with an atomic update:

    db.myCollection.update({_id: e._id}, {$set: {UserName: e.UserName.toLowerCase() } })
    

    Again, you could also do this from any of the drivers, the code will be very similar.


    EDIT: Remon brings up a good point. The $toLower command does exist as part of the aggregation framework, but this has nothing to do with updating. The documentation for updating is here.

    0 讨论(0)
  • 2020-12-01 05:58

    With the accepted solution I know its very trivial to do the same for an array of elements, just in case

    db.myCollection.find().forEach(
       function(e) {
          for(var i = 0; i < e.articles.length; i++) { 
              e.articles[i] = e.articles[i].toLowerCase(); 
          }
          db.myCollection.save(e); 
       }
    )
    
    0 讨论(0)
  • 2020-12-01 06:02

    Very similar solution but this worked me in new mongo 3.2 Execute the following in Mongo Shell or equivalent DB tools like MongoChef!

    db.tag.find({hashtag :{ $exists:true}}).forEach(
     function(e) {
       e.hashtag = e.hashtag.toLowerCase();
       db.tag.save(e);
    });
    
    0 讨论(0)
  • 2020-12-01 06:05

    A little late to the party but the below answer works very well with mongo 3.4 and above First get only those records which have different case and update only those records in bulk. The performance of this query is multifold better

    var bulk = db.myCollection.initializeUnorderedBulkOp();
    var count = 0
    db.myCollection.find({userId:{$regex:'.*[A-Z]'}}).forEach(function(e) {
     var newId = e.userId.toLowerCase();   
        bulk.find({_id:e._id}).updateOne({$set:{userId: newId}})
        count++
        if (count % 500 === 0) {
            bulk.execute();
            bulk = db.myCollection.initializeUnorderedBulkOp();
            count = 0;
        }
    })
    if (count > 0)  bulk.execute();
    
    0 讨论(0)
提交回复
热议问题