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

ссылки:

все еще довольно новый для Mongo db, но я пытаюсь обновить часть существующего документа внутри коллекции... к сожалению, приведенная выше ссылка не имеет примера обновления.

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

  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"));

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

EDIT:

Я просто попробовал и смог успешно обновить, отправив весь объект с новыми и / или обновленными полями, и это работает. Интересно, достаточно ли водитель умен, чтобы обновлять только наименьшее подмножество изменений, или он просто слепо обновляет все это? (В приведенном ниже случае это просто обновление поля 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

6 ответов


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

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

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

shapes.update((DBObject)JSON.parse(    "{ 'foo' : 'bar'}"),  
    (DBObject) JSON.parse(          "{ '$set' : { 'foo': 'bat'}}")   );

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

// 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' ) ) )

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

вы можете использовать категорию для создания BasicDBObjects более заводным способом...

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

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 )

без строителя


многие ответы на этот пост используют более старые версии драйвера Mongo Java. Если вы используете более новую версию драйвера Java (v3.0+) тогда предпочтительным методом, по-видимому, является использование объекта Document вместо интерфейса DBObject.

вот пример:

MongoClient client = new MongoClient();
MongoCollection<Document> fooCollection = client.getDatabase("test").getCollection("foo");

Bson filter = Filters.eq("_id", "123d45678c467bb433c99f99");
Bson updates = Updates.set("isFoo", true);
fooCollection.findOneAndUpdate(filter, updates);

этот ответ использует оболочку mongo, но показывает, как вы можете углубиться в структуру объекта JSON, чтобы изменить определенное поле без перезаписи остальных.

учитывая объект JSON в коллекции под названием "my_collection":

{ 
  "_id" : ObjectId("50fdb2a73f7bc7a5acecc4f8"), 
  "data" : { 
    "list" : [ 0, 1, 2, 7, 4, 5 ], 
    "subobj" : { 
       "var_a":"valuea",
       "var_b":"valueb" 
     }
  }
}

чтобы обновить 'var_b', не перезаписывая ничего другого:

db.my_collection.update({"_id":"50fdb2a73f7bc7a5acecc4f8"}, { "$set":{"data.subobj.var_b":"new_value"}})

чтобы обновить 3-й элемент в массиве 'list' со значением '99', не перезаписывая ничего другого:

db.my_collection.update({"_id":"50fdb2a73f7bc7a5acecc4f8"}, { "$set":{"data.list.2":"99"} } )

DBCollection dbCollection = db.getCollection("mycollection");
BasicDBObject dbObject = new BasicDBObject();
dbObject.put("_id", "3"); 
// your update condition - or the query
DBObject newObject =  dbCollection.find(dbObject).toArray().get(0);
// I just take the first element. Can iterate through as per your requirement if multiple fields        exist
newObject.put("key","value");
//add field, either a new field or any existing field
dbCollection.findAndModify(dbObject, newObject);

просто используйте вышеуказанные шаги . Можно изменить сведения, не затрагивая другие элементы, связанные с тем же ключом.


/ / update

WriteResult usr = (WriteResult)mongoOperation.upsert(new  Query(Criteria.where("name").is("till")),  

Update.update("password", "jk45"), "collection");

System.out.println("updatedUser : " + usr );