如何替换mongodb文档中的子字符串

Posted

技术标签:

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

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


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

我想用helloWorld替换helloWorldt得到:


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

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

【问题讨论】:

【参考方案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);
        
    ) 

【讨论】:

以上是关于如何替换mongodb文档中的子字符串的主要内容,如果未能解决你的问题,请参考以下文章

C语言中如何用一个字符串替换一个主串中的子串

PB中取字符串子串的函数是啥

C++编程,查找字符串子串并替换。

sql server 里类似replace的字符串子串删除

如何替换字符串的子字符串[重复]

带有字符串子字符串的SwiftUI 5.5初始化数组? [关闭]