使用 $toLower 更新 MongoDB 集合

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9423932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 12:30:14  来源:igfitidea点击:

Update MongoDB collection using $toLower

mongodb

提问by sveatch42

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

我有一个包含用户名的现有 MongoDB 集合。用户名包含小写和大写字母。

I want to update all the user names so they only contain lower case letters.

我想更新所有用户名,以便它们只包含小写字母。

I have tried this script, but it didn't work

我试过这个脚本,但没有用

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

回答by Gates VP

MongoDB does not have a concept of $toLoweras a command. The solution is to run a big forloop over the data and issue the updates individually.

MongoDB 没有$toLower作为命令的概念。解决方案是对数据运行一个大for循环并单独发布更新。

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

您可以在任何驱动程序中或从 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 $toLowercommand does exist as part of the aggregation framework, but this has nothing to do with updating. The documentation for updating is here.

编辑:雷蒙提出了一个好观点。该$toLower命令确实作为聚合框架的一部分存在,但这与更新无关。更新文档在这里

回答by Xavier Guihot

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

开始Mongo 4.2db.collection.update()可以接受聚合管道,最后允许根据自己的值更新字段:

// { 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):

    • $setis 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.

  • 第一部分{}是匹配查询,过滤要更新的文档(在本例中为所有文档)。

  • 第二部分[{ $set: { username: { $toLower: "$username" } } }],是更新聚合管道(注意方括号表示使用聚合管道):

    • $set是一个新的聚合运算符,在这种情况下会修改 的值"username"
    • 使用$toLower,我们"username"通过其小写版本修改 的值。
  • 不要忘记{ multi: true },否则只会更新第一个匹配的文档。

回答by Gajen Sunthara

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

非常相似的解决方案,但这在新的 mongo 3.2 中对我有用 在 Mongo Shell 或等效的数据库工具(如 MongoChef)中执行以下操作!

db.tag.find({hashtag :{ $exists:true}}).forEach(
 function(e) {
   e.hashtag = e.hashtag.toLowerCase();
   db.tag.save(e);
});

回答by Srisudhir T

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

聚会有点晚,但下面的答案适用于 mongo 3.4 及更高版本首先只获取那些具有不同大小写的记录,并只批量更新这些记录。此查询的性能好几倍

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

回答by Lyra

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 语句,如下所示:

if (e.UserName) e.UserName = e.UserName.toLowerCase();

回答by pravin

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