在过去的几天里,我一直在做一些研究,以找到答案,但没有运气。 :(
我有一个包含非常长字符串的字段的文档。我需要将另一个字符串连接到字段中已包含的字符串的末尾。
我现在的方式是,从Java中,我获取文档,在字段中提取字符串,将字符串追加到最后,最后用新字符串更新文档。
问题:字段中包含的字符串非常长,这意味着在Java中检索和使用此字符串需要时间和资源。此外,这是一种每秒进行几次的操作。
我的问题:有没有办法将字符串连接到现有字段,而不必首先获取(db.<doc>.find()
)字段的内容?实际上我想要的只是(field.contents += new_string
)。
我已经使用Javascript和eval
完成了这项工作,但是正如我发现的那样,MongoDB在执行javascript时会锁定数据库,这会使整个应用程序更慢。
提前谢谢你。 :)
答案 0 :(得分:16)
例如(它附加到开头,同样的故事):
前
{“_ id”:ObjectId(“56993251e843bb7e0447829d”),“name”:“London 城市“,”城市“:”伦敦“}
db.airports
.find( { $text: { $search: "City" } })
.forEach(
function(e, i){
e.name='Big ' + e.name;
db.airports.save(e);
}
)
后:
{“_ id”:ObjectId(“56993251e843bb7e0447829d”),“name”:“Big London 城市“,”城市“:”伦敦“}
答案 1 :(得分:4)
旧话题,但我遇到了同样的问题。 从mongo 2.4开始,您可以使用聚合框架中的$concat。
示例
考虑这些文件:
{
"_id" : ObjectId("5941003d5e785b5c0b2ac78d"),
"title" : "cov"
}
{
"_id" : ObjectId("594109b45e785b5c0b2ac97d"),
"title" : "fefe"
}
将fefe
追加到title
字段:
db.getCollection('test_append_string').aggregate(
[
{ $project: { title: { $concat: [ "$title", "fefe"] } } }
]
)
聚合的结果将是:
{
"_id" : ObjectId("5941003d5e785b5c0b2ac78d"),
"title" : "covfefe"
}
{
"_id" : ObjectId("594109b45e785b5c0b2ac97d"),
"title" : "fefefefe"
}
然后,您可以批量保存结果,请参阅this answer。
答案 2 :(得分:0)
这是不可能的。 您可以执行的一项优化是创建批量更新。 即获取10K文档,将相关字符串附加到其每个键, 然后将它们保存为单个批次。 大多数mongodb驱动程序都支持批处理操作。
答案 3 :(得分:0)
这是我拥有的一个文档的示例:
{
"_id" : 1,
"s" : 1,
"ser" : 2,
"p" : "9919871172",
"d" : ISODate("2018-05-30T05:00:38.057Z"),
"per" : "10"
}
要将字符串附加到任何字段,您可以在所有文档中运行forEach循环,然后更新所需的字段:
db.getCollection('jafar').find({}).forEach(function(el){
db.getCollection('jafar').update(
{p:el.p},
{$set:{p:'98'+el.p}})
})
答案 4 :(得分:0)
从Mongo 4.2
开始,db.collection.update()
可以接受聚合管道,最终允许根据字段的当前值更新字段:
// { a: "Hello" }
db.collection.update(
{},
[{ $set: { a: { $concat: [ "$a", "World" ] } } }],
{ multi: true }
)
// { a: "HelloWorld" }
第一部分{}
是匹配查询,用于过滤要更新的文档(在本例中为所有文档)。
第二部分[{ $set: { a: { $concat: [ "$a", "World" ] } } }]
是更新聚合管道(请注意方括号表示使用聚合管道)。 $set
($addFields
的别名)是一个新的聚合运算符,在这种情况下,它会替换字段的值(通过将a
本身与后缀"World"
连接起来)。注意如何a
根据其自身的值($a
)直接进行修改。
不要忘记{ multi: true }
,否则只会更新第一个匹配的文档。
答案 5 :(得分:-7)
db.getCollection('<collection>').update(
// query
{},
// update
{
$set: {<field>:this.<field>+"<new string>"}
},
// options
{
"multi" : true, // update only one document
"upsert" : false // insert a new document, if no existing document match the query
});