Добавить строку в конец существующего поля в 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 
    });