有效地查找和替换文档中的字符串

时间:2015-03-04 23:11:56

标签: javascript regex mongodb mongodb-query nosql

我有以下查询,在名称字段中查找 标签并将其替换为空格 - 以摆脱它们。
名称字符串可以包含1到多个 标记,例如

AA aa
AA  aa
AA   aa
AA    aa
AA AA aaaaaaaa

......就像那样。

  db.tests.find({'name':/.* .*/}).forEach(function(test){
      test.name = test.name.replace(" ","");
      db.tests.save(test);
   });

   db.tests.find({'name':/.*  .*/}).forEach(function(test){
      test.name = test.name.replace("  ","");
      db.tests.save(test);
   });

  db.tests.find({'name':/.*   .*/}).forEach(function(test){
      test.name = test.name.replace("   ","");
      db.tests.save(test);
   });

除了重复相同的查询模式之外,还有更好的解决方案来处理这种情况,从而减少重复和提高性能吗?

3 个答案:

答案 0 :(得分:14)

当然,如果您只想从文本中删除 个实体,那么您只需进行全局匹配并替换:

db.tests.find({ "name": /\ /g }).forEach(function(doc) {
    doc.name = doc.name.replace(/ /g,"");
    db.tests.update({ "_id": doc._id },{ "$set": { "name": doc.name } });
});

因此,不需要写出每个组合,正则表达式将替换为/g选项非常匹配。可能还会使用/m来表示多行是你的名字" string包含换行符。查看基本regexer example

还建议使用$set,以便仅修改您真正想要的字段,而不是.save()整个文档。自阅读文档以来,流量减少,覆盖另一个流程可能做出的更改的可能性更小。

理想情况下,您可以将批量操作API与MongoDB 2.6及更高版本一起使用。这允许更新"批次"所以客户端和服务器之间的流量再次减少:

var bulk = db.tests.initializeOrderedBulkOp();
var count = 0;

db.tests.find({ "name": /\ /g }).forEach(function(doc) {
    doc.name = doc.name.replace(/ /g,"");
    bulk.find({ "_id": doc._id })
        .updateOne({ "$set": { "name": doc.name } });
    count++;

    if ( count % 1000 == 0 ) {
        bulk.execute();
        bulk = db.tests.initializeOrderedBulkOp();
    }
});

if  ( count % 1000 != 0 )
    bulk.execute();

这是您改善这一点的主要方法。遗憾的是,MongoDB更新语句无法以这种方式将现有值用作其更新表达式的一部分,因此唯一的方法是循环,但您可以做很多事情来减少操作,如图所示。

答案 1 :(得分:2)

现在,

  • 开始Mongo 4.2db.collection.updateManydb.collection.update的别名)可以接受聚合管道,最终允许根据其自身值更新字段。
  • Mongo 4.4开始,新的聚合运算符$replaceAll使替换字符串的一部分变得非常容易。
// { "name" : "AA aa" }
// { "name" : "AA  aa" }
// { "name" : "AA AA aaaaaaaa" }
db.collection.updateMany(
  { name: { $regex: /\&nbsp\;/ } },
  [{
    $set: { name: {
      $replaceAll: { input: "$name", find: " ", replacement: "" }
    }}
  }]
)
// { "name" : "AAaa" }
// { "name" : "AAaa" }
// { "name" : "AAAAaaaaaaaa" }
  • 第一部分({ name: { $regex: /\&nbsp\;/ } })是匹配查询,用于过滤要更新的文档(包含" "的文档)
  • 第二部分($set: { name: {...)是更新聚合管道(请注意方括号表示使用聚合管道):
    • $set是新的聚合运算符(Mongo 4.2),在这种情况下,它将替换字段的值。
    • 使用新的$replaceAll运算符来计算新值。请注意,如何根据name自身的值($name)直接对其进行修改。

答案 2 :(得分:1)

由于 age location name type 0 12 so john 1 12 so jane 2 20 NaN james NaN 3 30 NaN rich NaN 在MongoDB搜索中没有显示为字符串,因此,我使用了UNICODE  来代替字符串,如下所示:

u00a0

在这里,我将名称数据字段中的db.tests.find({}).forEach(function (x) { x.name = x.name.replace(/\u00a0/g, ' '); db.tests.save(x); }); 替换为空白