我有以下查询,在名称字段中查找
标签并将其替换为空格 - 以摆脱它们。
名称字符串可以包含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);
});
除了重复相同的查询模式之外,还有更好的解决方案来处理这种情况,从而减少重复和提高性能吗?
答案 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.2
,db.collection.updateMany
(db.collection.update
的别名)可以接受聚合管道,最终允许根据其自身值更新字段。Mongo 4.4
开始,新的聚合运算符$replaceAll
使替换字符串的一部分变得非常容易。// { "name" : "AA aa" }
// { "name" : "AA aa" }
// { "name" : "AA AA aaaaaaaa" }
db.collection.updateMany(
{ name: { $regex: /\ \;/ } },
[{
$set: { name: {
$replaceAll: { input: "$name", find: " ", replacement: "" }
}}
}]
)
// { "name" : "AAaa" }
// { "name" : "AAaa" }
// { "name" : "AAAAaaaaaaaa" }
{ name: { $regex: /\ \;/ } }
)是匹配查询,用于过滤要更新的文档(包含" "
的文档)$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);
});
替换为空白