Как обновить поля документов в mongo db с помощью драйвера java?

Ссылки:

Все еще довольно плохо знакомы с Монго БД, но я пытаюсь обновить часть существующего документа внутри коллекции ... к сожалению, ссылка выше не имеет пример обновления.

По сути, я просто хочу иметь возможность:

  1. Добавить новые поля в документе
  2. Обновить существующие поля документа к новому значению

Вот мой код (Grails + Groovy + Java + MongoDB + драйвер Java):

def shape = mongo.shapes.findOne(new BasicDBObject("data", "http://www.foo.com")); // get the document
mongo.shapes.update(new BasicDBObject("_id", shape._id), new BasicDBObject("isProcessed", 0));  // add a new "isProcessed" field set to 0
mongo.shapes.update(new BasicDBObject("_id", shape._id), new BasicDBObject("data", "http://www.bar.com"));

Это в значительной степени забивает весь объект ... Я мог бы попытаться просто изменить исходный объект формы и затем запустить обновить на этом. Но до тех пор, кто-нибудь имел опыт обновления только отдельных полей (а не всего документа)?

РЕДАКТИРОВАТЬ:

Я только что попробовал и смог успешно обновить, отправив весь объект с новыми и / или обновленные поля, и это работает. Интересно, достаточно ли умен этот драйвер, чтобы обновлять только малейшее подмножество изменений или он просто вслепую обновляет все? (В приведенном ниже случае это просто обновление поля foo на проводе или на всем документе формы?)

Код:

def shape = mongo.shapes.findOne(); // get the first shape to use as a base
shape.removeField("_id");  // remove the id field
shape.put("foo","bar");  // add a new field "foo"
mongo.shapes.insert(shape);  // insert the new shape
def shape2 = mongo.shapes.findOne(new BasicDBObject("foo", "bar"));  // get the newly inserted shape (and more importantly, it's id)
shape2.put("foo", "bat");  // update the "foo" field to a new value
mongo.shapes.update(new BasicDBObject("_id", shape2._id), shape2);  // update the existing document in mongo

18
задан Parvin Gasimzade 14 August 2012 в 13:09
поделиться

2 ответа

Интересно, достаточно ли умен драйвер, чтобы обновлять только наименьшее подмножество изменений, или он просто вслепую обновляет все?

Нет, если вы используете «обычный» метод обновления, весь объект будет отправлен по сети. Подозреваю, что сам сервер базы данных будет достаточно умен, чтобы обновлять только нужные индексы (а не те, которые не изменились), если это возможно (т.е. объект можно было обновить на месте и его не нужно было перемещать, потому что он слишком вырос много)

Что вы можете сделать, так это использовать функции "атомарного модификатора обновления". В документации по Java они немного упрощены, но, поскольку драйвер просто передает JSON, материал из руководств, отличных от Java, должен работать, например:

shapes.update((DBObject)JSON.parse(    "{ 'foo' : 'bar'}"),  
    (DBObject) JSON.parse(          "{ '$set' : { 'foo': 'bat'}}")   );
12
ответ дан 30 November 2019 в 07:49
поделиться

Нашел пример здесь, который, похоже, показывает использование вызова обновления. Итак, для вашего примера, я считаю, что что-то вроде этого должно работать?

// Find an object
def shape2 = mongo.shapes.findOne( new BasicDBObject( 'foo', 'bar' ) )
// And update the foo field from 'bar' to 'bat'
mongo.shapes.update( shape2, new BasicDBObject( '$set', new BasicDBObject( 'foo', 'bat' ) ) )

Редактировать

Вы могли бы использовать категорию для создания ваших объектов BasicDBObject более плавным образом...

Что-то вроде этого может сделать это:

class BasicDBObjectMapBuilder {
  static String toDbObj( String s ) { s }
  static BasicDBObject toDbObj( Map m ) {
    m.inject( null ) { r, it -> new BasicDBObject( it.key, it.value.toDbObj() ) }
  }
}

use( BasicDBObjectMapBuilder ) {
  def shape2 = mongo.shapes.findOne( new BasicDBObject( 'foo', 'bar' ) )
  // And update the foo field from 'bar' to 'bat'
  mongo.shapes.update( shape2, [ '$set':[ 'foo', 'bat' ] ].toDbObj() )
}

Хотя я не проверял это...

Редактировать 2

На самом деле, BasicDBObject — это карта, поэтому вы должны иметь возможность:

  mongo.shapes.update( shape2, [ '$set':[ 'foo', 'bat' ] ] as BasicDBObject )

без использования компоновщика

11
ответ дан 30 November 2019 в 07:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: