【问题标题】:How to replace substring in mongodb document如何替换mongodb文档中的子字符串
【发布时间】:2012-09-25 19:29:14
【问题描述】:

我在表单集合中有很多 mongodb 文档:

{
....
"URL":"www.abc.com/helloWorldt/..."
.....
}

我想用helloWorld替换helloWorldt得到:

{
....
"URL":"www.abc.com/helloWorld/..."
.....
}

如何为我的收藏中的所有文档实现这一点?

【问题讨论】:

    标签: mongodb mongodb-.net-driver mongo-shell mongodb-update


    【解决方案1】:
    db.media.find({mediaContainer:"ContainerS3"}).forEach(function(e,i) {
        e.url=e.url.replace("//a.n.com","//b.n.com");
        db.media.save(e);
    });
    

    【讨论】:

    • 你能详细说明一下吗?它是如何工作的代码的含义是什么?也适用于其他用户?
    • 太棒了。我的情况是——我有一个字段是一个数组——所以我不得不添加一个额外的循环。我的查询是:db.getCollection("profile").find({"photos": {$ne: "" }}).forEach(function(e,i) { e.photos.forEach(function(url, j) { url = url.replace("http://a.com", "https://dev.a.com"); e.photos[j] = url; }); db.getCollection("profile").save(e); eval(printjson(e)); })
    • @doe "e" 这里表示找到的每个文档的副本。该副本的 url 值(区分大小写,请注意,这与提问者的“url”不同)根据其原始 url 值进行更新。 "e" 将其所有原始字段与一个修改后的字段一起保留。将 e 保存回集合会覆盖原始的“e”。这里不需要“i”,可以从函数声明中删除。
    • 请给其他用户解释一下??
    • 确实可以只更新已更改的一个字段,而不是读取和写回整个文档吗?
    【解决方案2】:

    现在,

    • Mongo 4.2db.collection.updateManydb.collection.update 的别名)开始可以接受聚合管道,最终允许根据自己的值更新字段。
    • Mongo 4.4 开始,新的聚合运算符$replaceOne 可以很容易地替换字符串的一部分。
    // { URL: "www.abc.com/helloWorldt/..." }
    // { URL: "www.abc.com/HelloWo/..." }
    db.collection.updateMany(
      { URL: { $regex: /helloWorldt/ } },
      [{
        $set: { URL: {
          $replaceOne: { input: "$URL", find: "helloWorldt", replacement: "helloWorld" }
        }}
      }]
    )
    // { URL: "www.abc.com/helloWorld/..." }
    // { URL: "www.abc.com/HelloWo/..." }
    
    • 第一部分 ({ URL: { $regex: /helloWorldt/ } }) 是匹配查询,用于过滤要更新的文档(包含 "helloWorldt" 的文档),以便加快查询速度。
    • 第二部分($set: { URL: {...)是更新聚合管道(注意方括号表示使用聚合管道):
      • $set 是一个新的聚合运算符 (Mongo 4.2),在这种情况下会替换字段的值。
      • 使用新的$replaceOne 运算符计算新值。请注意URL 是如何根据其自身的值($URL)直接修改的。

    Mongo 4.4 和开始Mongo 4.2 之前,由于缺少正确的字符串$replace 运算符,我们必须使用$concat$split 的普通组合:

    db.collection.updateMany(
      { URL: { $regex: "/helloWorldt/" } },
      [{
        $set: { URL: {
          $concat: [
            { $arrayElemAt: [ { $split: [ "$URL", "/helloWorldt/" ] }, 0 ] },
            "/helloWorld/",
            { $arrayElemAt: [ { $split: [ "$URL", "/helloWorldt/" ] }, 1 ] }
          ]
        }}
      }]
    )
    

    【讨论】:

    • 谢谢,它可以与find中的正则表达式一起使用吗?
    • 谢谢,替换时是否需要斜杠(“/”)?
    • @dhalfageme 我在后一个例子中看到了混乱。 $regex 运算符(即$regex: "/helloWorldt/")后面的正斜杠是正则表达式分隔符,这是必需的。在示例中的其他任何地方,正斜杠都是 URL 路径分隔符,可能不是必需的。只有当 OP 的 URL 的路径包含他们想要保留的 /helloWorldthirsty/ 时,它们才是必需的。
    【解决方案3】:

    目前,您不能使用字段的值来更新它。因此,您必须遍历文档并使用函数更新每个文档。这里有一个示例说明您可以如何做到这一点:MongoDB: Updating documents using data from the same document

    【讨论】:

      【解决方案4】:

      要替换文档中 ALL 次出现的子字符串,请使用:

      db.media.find({mediaContainer:"ContainerS3"}).forEach(function(e,i) {
      var find = "//a.n.com";
      var re = new RegExp(find, 'g');
      e.url=e.url.replace(re,"//b.n.com");
      db.media.save(e);
      });
      

      【讨论】:

      • 变量不需要在循环中,所以把它们放在前面。
      • 变量应该是常量。
      【解决方案5】:

      使用 mongodump、bsondump 和 mongoimport。

      有时 mongodb 集合可能会因嵌套数组/对象等变得不那么复杂,在这些集合中围绕它们构建循环相对困难。我的解决方法有点原始,但在大多数情况下都适用,无论集合的复杂性如何。

      1.使用 mongodump 将集合导出到 .bson

      mongodump --db=<db_name> --collection=<products> --out=data/
      

      2。使用 bsondump 将 .bson 转换为 .json 格式

      bsondump --outFile products.json data/<db_name>/products.bson
      

      3.将 .json 文件中的字符串替换为 sed(用于 linux 终端)或任何其他工具

      sed -i 's/oldstring/newstring/g' products.json
      

      4.使用带有 --drop 标签的 mongoimport 导入 .json 集合,它将在导入之前删除集合

      mongoimport --db=<db_name>  --drop --collection products <products.json
      

      或者,您可以在 mongoimport 中使用 --uri 进行连接 和mongodump

      例子

      mongodump --uri "mongodb://mongoadmin:mystrongpassword@10.148.0.7:27017,10.148.0.8:27017,10.148.0.9:27017/my-dbs?replicaSet=rs0&authSource=admin" --collection=products --out=data/
      

      【讨论】:

        【解决方案6】:

        节点。使用mongodb package from npm

        db.collection('ABC').find({url: /helloWorldt/}).toArray((err, docs) => {
          docs.forEach(doc => {
            let URL = doc.URL.replace('helloWorldt', 'helloWorld');
            db.collection('ABC').updateOne({_id: doc._id}, {URL});
          });
        });
        

        【讨论】:

          【解决方案7】:

          我对所选答案(@Naveed 的答案)的评论的格式已被打乱 - 因此将其添加为答案。所有功劳归于 Naveed。

          ----------------------------------------------- -----------------------

          太棒了。 我的情况是——我有一个字段是一个数组——所以我不得不添加一个额外的循环。

          我的查询是:

          db.getCollection("profile").find({"photos": {$ne: "" }}).forEach(function(e,i) {
              e.photos.forEach(function(url, j) {
                  url = url.replace("http://a.com", "https://dev.a.com");
                  e.photos[j] = url;
              });
              db.getCollection("profile").save(e);
              eval(printjson(e));
          })
          

          【讨论】:

            【解决方案8】:

            现在你可以做到了!

            我们可以使用 Mongo 脚本来动态操作数据。它对我有用!

            我使用这个脚本来更正我的地址数据。

            当前地址示例:“第五大道 12 号”。

            我想删除最后一个多余的逗号,即预期的新地址“No.12, FIFTH AVENUE”。

            var cursor = db.myCollection.find().limit(100);
            
            while (cursor.hasNext()) {
              var currentDocument = cursor.next();
            
              var address = currentDocument['address'];
              var lastPosition = address.length - 1;
            
              var lastChar = address.charAt(lastPosition);
            
              if (lastChar == ",") {
            
                var newAddress = address.slice(0, lastPosition);
            
            
                currentDocument['address'] = newAddress;
            
                db.localbizs.update({_id: currentDocument._id}, currentDocument);
            
              }
            }
            

            希望这会有所帮助!

            【讨论】:

            • 有什么办法可以替换mongodb中大二进制字符串的部分子字符串?
            【解决方案9】:

            这可以通过在方法replace 的第一部分中使用Regex 来完成,它将用第二个字符串替换该字符串的[all if g in regex pattern] 出现,这与 Javascript 中的正则表达式相同,例如:

            const string = "www.abc.com/helloWorldt/...";
            console.log(string);
            var pattern = new RegExp(/helloWorldt/)
            replacedString = string.replace(pattern, "helloWorld");
            console.log(replacedString);

            由于正则表达式正在替换字符串,现在我们可以通过 forEach 方法查找和迭代每个元素并在 forEach 循环中一一保存,从而轻松地做到这一点:

            > db.media.find()
            { "_id" : ObjectId("5e016628a16075c5bd26fbe3"), "URL" : "www.abc.com/helloWorld/" }
            { "_id" : ObjectId("5e016701a16075c5bd26fbe4"), "URL" : "www.abc.com/helloWorldt/" }
            > 
            > db.media.find().forEach(function(o) {o.URL = o.URL.replace(/helloWorldt/, "helloWorld"); printjson(o);db.media.save(o)})
            {
                "_id" : ObjectId("5e016628a16075c5bd26fbe3"),
                "URL" : "www.abc.com/helloWorld/"
            }
            {
                "_id" : ObjectId("5e016701a16075c5bd26fbe4"),
                "URL" : "www.abc.com/helloWorld/"
            }
            > db.media.find()
            { "_id" : ObjectId("5e016628a16075c5bd26fbe3"), "URL" : "www.abc.com/helloWorld/" }
            { "_id" : ObjectId("5e016701a16075c5bd26fbe4"), "URL" : "www.abc.com/helloWorld/" }
            >
            

            【讨论】:

              【解决方案10】:

              如果你想搜索一个子字符串,并用另一个替换它,你可以尝试如下,

                  db.collection.find({ "fieldName": /.*stringToBeReplaced.*/ }).forEach(function(e, i){
                      if (e.fieldName.indexOf('stringToBeReplaced') > -1) {
                        e.content = e.content.replace('stringToBeReplaced', 'newString');
                        db.collection.update({ "_id": e._id }, { '$set': { 'fieldName': e.fieldName} }, false, true);
                      }
                  }) 
              

              【讨论】:

                猜你喜欢
                • 2020-04-20
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-04-20
                • 1970-01-01
                • 2014-06-09
                相关资源
                最近更新 更多