Добавить строку в конец существующего поля в MongoDB
У меня есть документ с полем, содержащим очень длинную строку. Мне нужно объединить другую строку до конца строки, уже содержащейся в поле.
Теперь я делаю это так, что из Java я извлекаю документ, извлекаю строку в поле, добавляю строку в конец и, наконец, обновляю документ новой строкой.
Проблема: строка, содержащаяся в поле, очень длинная, что означает, что для извлечения и работы с этой строкой в Java требуются время и ресурсы. Кроме того, эта операция выполняется несколько раз в секунду.
Мой вопрос: есть ли способ объединить строку с существующим полем, без необходимости db.<doc>.find()
извлекать (db.<doc>.find()
) содержимое поля? На самом деле все, что я хочу, это (field.contents += new_string
).
Я уже сделал эту работу, используя Javascript и eval
, но, как я выяснил, MongoDB блокирует базу данных при выполнении javascript, что делает приложение в целом еще медленнее.
Ответы
Ответ 1
Например (добавьте начало, ту же историю):
перед
{ "_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 Город", "город": "Лондон" }
Ответ 2
Старая тема, но у меня была такая же проблема.
Начиная с 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"
}
Затем вы можете сохранить результаты с помощью массива, см. этот ответ для этого.
Ответ 3
Это было бы невозможно.
Одна оптимизация, которую вы можете сделать, - это создавать партии обновлений.
то есть извлекать документы 10K, добавлять соответствующие строки к каждому из своих ключей,
а затем сохранить их как одну партию.
Большинство драйверов mongodb поддерживают пакетные операции.
Ответ 4
это образец одного документа, который у меня есть:
{
"_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}})
})
Ответ 5
Начиная с 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 }
, иначе будет обновлен только первый соответствующий документ.
Ответ 6
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
});