如何使用java驱动程序更新mongo db中的文档字段?
参考文献:
- http://www.mongodb.org/display/DOCS/Java+Tutorial
仍然是mongo db的新手,但我正在尝试更新集合中现有文档的一部分……遗憾的是,上面的链接没有更新示例。
基本上,我只是希望能够:
- 向文档添加新字段
- 将文档的现有字段更新为新值
这是我的代码(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
我想知道驱动程序是否足够智能,只更新最小的更改子集,或者只是盲目更新整个事物?
不,如果您使用“正常”更新方法,整个对象将通过网络发送。 我怀疑数据库服务器本身就足够聪明,只能更新必要的索引(而不是那些没有改变的索引),如果可能的话(即对象可以在适当的位置更新而不必移动,因为它也增长了许多)
你可以做的是使用“primefaces更新修饰符”function。 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是一个Map,所以你应该能够做到:
mongo.shapes.update( shape2, [ '$set':[ 'foo', 'bat' ] ] as BasicDBObject )
不需要建设者
这篇文章的很多答案都是使用旧版本的Mongo Java Driver。 如果您使用的是较新版本的Java驱动程序(v3.0 +),则首选方法似乎是使用Document对象而不是DBObject接口。
这是一个例子:
MongoClient client = new MongoClient(); MongoCollection fooCollection = client.getDatabase("test").getCollection("foo"); Bson filter = Filters.eq("_id", "123d45678c467bb433c99f99"); Bson updates = Updates.set("isFoo", true); fooCollection.findOneAndUpdate(filter, updates);
这个答案使用了mongo shell,但展示了如何深入到JSON对象结构来修改特定字段而不覆盖其余字段。
给定名为“my_collection”的集合中的JSON对象:
{ "_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"}})
要使用值“99”更新数组“list”中的第3个元素,而不覆盖其他任何内容:
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);
只需使用上述步骤即可。 您可以更改详细信息,而不会影响与同一密钥关联的其他项目。
//更新
WriteResult usr = (WriteResult)mongoOperation.upsert(new Query(Criteria.where("name").is("till")), Update.update("password", "jk45"), "collection"); System.out.println("updatedUser : " + usr );