从字符串值中删除空格(前导和尾随)

Posted

技术标签:

【中文标题】从字符串值中删除空格(前导和尾随)【英文标题】:Removing white spaces (leading and trailing) from string value 【发布时间】:2014-05-28 05:56:27 【问题描述】:

我已经使用 mongoimport 在 mongo 中导入了一个 csv 文件,我想从我的字符串值中删除前导和尾随空格。

是否可以直接在 mongo 中对所有集合使用修剪功能,还是我需要为此编写脚本?

我的收藏包含以下元素:


  "_id" : ObjectId("53857680f7b2eb611e843a32"),
  "category" : "Financial & Legal Services "

我想对所有集合应用修剪功能,以便"category" 不应包含任何前导和尾随空格。

【问题讨论】:

如果可以,请在导入前修复 CSV。 【参考方案1】:

当前在 MongoDB 中的更新无法在应用更新时引用当前字段的现有值。所以你将不得不循环:

db.collection.find(, "category": 1 ).forEach(function(doc) 
   doc.category = doc.category.trim();
   db.collection.update(
        "_id": doc._id ,
        "$set":  "category": doc.category  
   );
)

注意此处使用$set 运算符和预计的“类别”字段只是为了减少网络流量”

您可以使用 $regex 限制该进程以匹配:

db.collection.find( 
    "$and": [
         "category": /^\s+/ ,
         "category": /\s+$/ 
    ]
)

或者甚至是纯 $regex 而不使用 $and,您只需要在 MongoDB 中将多个条件应用于同一字段。否则 $and 对所有参数都是隐含的:

db.collection.find( "category": /^\s+|\s+$/ )

这将匹配的文档限制为仅处理具有前导或尾随空格的文档。

如果您担心要查看的文档数量,如果您有可用的 MongoDB 2.6 或更高版本,批量更新应该会有所帮助:

var batch = [];
db.collection.find( "category": /^\s+|\s+$/ , "category": 1 ).forEach(
    function(doc) 
        batch.push(
            "q":  "_id": doc._id ,
            "u":  "$set":  "category": doc.catetgory.trim()  
        );

        if ( batch.length % 1000 == 0 ) 
            db.runCommand("update", batch);
            batch = [];
        
    
);

if ( batch.length > 0 )
    db.runCommand("update", batch);

对于 MongoDB 2.6 及更高版本,甚至使用 bulk operations API:

var counter = 0;
var bulk = db.collection.initializeOrderedBulkOp();
db.collection.find( "category": /^\s+|\s+$/ , "category": 1).forEach(
    function(doc) 
        bulk.find( "_id": doc._id ).update(
            "$set":  "category": doc.category.trim() 
        );
        counter = counter + 1;

        if ( counter % 1000 == 0 ) 
            bulk.execute();
            bulk = db.collection.initializeOrderedBulkOp();
        
    
);

if ( counter > 1 )
    bulk.execute();

最好使用 bulkWrite() 完成现代 API,它使用批量操作 API(技术上 现在所有事情 都可以)但实际上以一种安全回归的方式 使用旧版本的 MongoDB。虽然老实说,这意味着在 MongoDB 2.6 之前,使用这样的版本您将无法获得官方支持选项。编码更清晰:

var batch = [];
db.collection.find( "category": /^\s+|\s+$/ , "category": 1).forEach(
  function(doc) 
    batch.push(
      "updateOne": 
        "filter":  "_id": doc._id ,
        "update":  "$set":  "category": doc.category.trim()  
      
    );

    if ( batch.legth % 1000 == 0 ) 
      db.collection.bulkWrite(batch);
      batch = [];
    
  
);

if ( batch.length > 0 ) 
  db.collection.bulkWrite(batch);
  batch = [];

每 1000 个文档只向服务器发送一次操作,或者在 64MB BSON 限制下进行尽可能多的修改。

只是解决问题的几种方法。或者在导入之前先更新您的 CSV 文件。

【讨论】:

【参考方案2】:

尼尔对批量操作 api 的回答的小修正

是的

initializeOrderedBulkOp

不是

initializeBulkOrderedOp

你也错过了

counter++;

在forEach里面,总结一下

var counter = 1;
var bulk = db.collection.initializeOrderedBulkOp();
db.collection.find( "category": /^\s+|\s+$/ , "category": 1).forEach(
    function(doc) 
        bulk.find( "_id": doc._id ).update(
            "$set":  "category": doc.category.trim() 
        );

        if ( counter % 1000 == 0 ) 
            bulk.execute();
            counter = 1;
        
        counter++;
    
);

if ( counter > 1 )
    bulk.execute();

注意:我没有足够的声誉来发表评论,因此添加了一个答案

【讨论】:

【参考方案3】:

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

Mongo 4.0 开始,$trim 运算符可以应用于字符串以删除其前导/尾随空格:

//  category: "Financial & Legal Services " 
//  category: " IT  " 
db.collection.update(
  ,
  [ $set:  category:  $trim:  input: "$category"    ],
   multi: true 
)
//  category: "Financial & Legal Services" 
//  category: "IT" 

注意:

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

第二部分[ $set: category: $trim: input: "$category" ]是更新聚合管道(注意方括号表示使用聚合管道):

$set 是一个新的聚合运算符,在这种情况下替换了 "category" 的值。 我们使用$trim 修改和修整"category" 的值。 请注意,$trim 可以采用可选参数 chars,它允许指定要修剪的字符。

不要忘记 multi: true ,否则只会更新第一个匹配的文档。

【讨论】:

为我工作。谢谢【参考方案4】:

您可以在 MongoDB 更新命令中在游标方法中执行 javascript

db.collection.find(, "category": 1 ).forEach(function(doc) 
  db.collection.update(
     "_id": doc._id ,
     "$set":  "category": doc.category.trim()  
  );
)

如果您有大量记录并且需要批处理,您可能想在此处查看其他答案。

【讨论】:

与公认答案的第一部分基本相同,但我喜欢这个,因为它有点短。谢谢。

以上是关于从字符串值中删除空格(前导和尾随)的主要内容,如果未能解决你的问题,请参考以下文章

Javascript从多行字符串中删除前导和尾随空格

如何删除前导和尾随的空格以及字符串中的多个空格? [复制]

如何在Java中仅删除字符串的尾随空格并保留前导空格?

前导和尾随空格剪切 + 中间空格替换

从 Java 字符串中去除前导和尾随空格

如何取回使用 .trim 删除的所有原始前导和尾随空格? [复制]