从字符串值中删除空格(前导和尾随)
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()
);
)
如果您有大量记录并且需要批处理,您可能想在此处查看其他答案。
【讨论】:
与公认答案的第一部分基本相同,但我喜欢这个,因为它有点短。谢谢。以上是关于从字符串值中删除空格(前导和尾随)的主要内容,如果未能解决你的问题,请参考以下文章