繁体   English   中英

MongoDB 聚合有条件地更新所有包含大量文档的集合中的用户名

[英]MongoDB Aggregation to conditionally update usernames in all of the collection with large number of documents

我们在 Mongo Atlas 中有一个包含大量文档的userLogin集合。 如果字段不是小写,我必须编写一个聚合来小写username名字段。 该集合包含大量文档(超过 500,000 个)。

我编写了以下聚合函数,如果字段有任何不是小写的字符,它会小写该字段。 如果用户名字段中的值与其小写值不相等,我将使用$match检查,在这种情况下,使用$set我将字段设置为小写值。

await userLogin.aggregate([
    
      {
        '$match': {
          '$expr': {
            '$ne': [
              '$username', {
                '$toLower': '$username'
              }
            ]
          }
        }
      }, {
        '$set': {
          'username': {
            '$toLower': '$username'
          }
        }
      }
    ,
    {
      $out: 'userLogin',
    },
  ]);

它适用于用户名中包含大写字符的文档。 但是,如果用户名已经是小写,则文档将被删除。 我究竟做错了什么?

编辑:由于用户名上有一个唯一索引,如果集合中已经存在具有小写用户名的文档,则应跳过当前正在处理的文档(用户名变为小写)。

在您的情况下, $match条件正在过滤掉已经是lowercase的文档,这是不必要的。 简单地说,这应该足够了:

await userLogin.aggregate([
     {
        '$set': {
          'username': {
            '$toLower': '$username'
          }
        }
      }
    ,
    {
      $out: 'userLogin',
    },
  ])

这将设置username ,不管它是否有大写字符。

另外$out完全替换了集合,这就是为什么使用$match运行时文档似乎被删除的原因。 要么删除$match ,要么使用$merge阶段而不是$out

这是$merge 文档的链接。

它应该是这样的:

await userLogin.aggregate([
    
      {
        '$match': {
          '$expr': {
            '$ne': [
              '$username', {
                '$toLower': '$username'
              }
            ]
          }
        }
      }, {
        '$set': {
          'username': {
            '$toLower': '$username'
          }
        }
      }
    ,
    {
      $merge:  { 
        into: "userLogin", 
        on: "_id", 
        whenMatched: "replace"
       },
    },
   ]);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM