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

Mongodb 从字符串值中删除空格(前导和尾随),mongodb,mongodb-query,trim,Mongodb,Mongodb Query,Trim,我已经使用mongoimport在mongo中导入了一个csv文件,我想从字符串值中删除前导空格和尾随空格 是否可以直接在mongo中对所有集合使用修剪函数,或者我需要为此编写脚本 “我的收藏”包含以下元素: { "_id" : ObjectId("53857680f7b2eb611e843a32"), "category" : "Financial & Legal Services " } 我希望对所有集合应用修剪功能,以便“category”不应包含任何前导空格和尾随空格。

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

是否可以直接在mongo中对所有集合使用修剪函数,或者我需要为此编写脚本

“我的收藏”包含以下元素:

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

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

在应用更新时,MongoDB中的更新当前不可能引用当前字段的现有值。因此,您必须循环:

db.collection.find({},{ "category": 1 }).forEach(function(doc) {
   doc.category = doc.category.trim();
   db.collection.update(
       { "_id": doc._id },
       { "$set": { "category": doc.category } }
   );
})
注意到运营商的使用和预测的“类别”字段仅用于减少网络流量”

您可以限制要匹配的进程:

db.collection.find({ 
    "$and": [
        { "category": /^\s+/ },
        { "category": /\s+$/ }
    ]
})
或者,即使是纯的,也不需要在MongoDB中使用它,在MongoDB中,多个条件将应用于同一字段。否则,所有参数都隐含:

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及以上版本中:

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文件。

对Neil for bulk operations api的答案进行了一些小的更正

是的

initializeOrderedBulkOp
不是

你也错过了

counter++;
在forEach内部,因此概括而言

var计数器=1;
var bulk=db.collection.initializeOrderedBulkOp();
db.collection.find({“category”:/^\s+|\s+$/},{“category”:1}).forEach(
功能(doc){
bulk.find({“\u id”:doc.\u id}).update({
“$set”:{“category”:doc.category.trim()}
});
如果(计数器%1000==0){
bulk.execute();
计数器=1;
}
计数器++;
}
);
如果(计数器>1)
bulk.execute();

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

当位于游标方法中时,您可以在MongoDB update命令中执行javascript:

db.collection.find({},{ "category": 1 }).forEach(function(doc) {
  db.collection.update(
    { "_id": doc._id },
    { "$set": { "category": doc.category.trim() } }
  );
})
如果您有大量记录并且需要批处理,您可能需要在此处查看其他答案。

  • 启动
    mongo4.2
    ,可以接受聚合管道,最后允许根据字段自身的值更新字段

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

/{类别:“金融和法律服务”}
//{类别:“IT”}
db.collection.update(
{},
[{$set:{category:{$trim:{input:$category'}}}],
{multi:true}
)
//{类别:“金融和法律服务”}
//{类别:“IT”}
请注意:

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

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

    • 是一个新的聚合运算符,在本例中它将替换
      “category”
      的值
    • 使用,我们修改并修剪
      “category”
      的值
    • 请注意,
      $trim
      可以采用可选参数
      chars
      ,该参数允许指定要修剪的字符
  • 不要忘记
    {multi:true}
    ,否则只会更新第一个匹配的文档


如果可以,只需在导入前修复CSV。它与公认答案的第一部分基本相同,但我喜欢这一部分,因为它略短。谢谢。为我工作。谢谢
db.collection.find({},{ "category": 1 }).forEach(function(doc) {
  db.collection.update(
    { "_id": doc._id },
    { "$set": { "category": doc.category.trim() } }
  );
})