如何使用 java 驱动程序更新 mongo db 中的文档字段?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3580529/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I update fields of documents in mongo db using the java driver?
提问by longda
References:
参考:
Still pretty new to mongo db but I'm trying to update part of an existing document inside a collection... unfortunately, the link above doesn't have an update example.
对 mongo db 仍然很新,但我正在尝试更新集合中现有文档的一部分……不幸的是,上面的链接没有更新示例。
Essentially, i just want to be able to:
本质上,我只想能够:
- Add new fields to a document
- Update existing fields of a document to a new value
- 向文档添加新字段
- 将文档的现有字段更新为新值
Here's my code (Grails + Groovy + Java + MongoDB + the java driver):
这是我的代码(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"));
This pretty much clobbers the entire object... I might try just modifying the original shape object and then running the update on that. But until then, does anyone have experience updating just individual fields (rather than the entire document)?
这几乎破坏了整个对象......我可能会尝试修改原始形状对象,然后在其上运行更新。但在那之前,有没有人有过只更新单个字段(而不是整个文档)的经验?
EDIT:
编辑:
I just tried it and was able to successfully update by sending the entire object across with new and/or updated fields and that works. I wonder if the driver is smart enough to only update the smallest subset of changes or if it's just blindly updating the entire thing? (In the case below, is it just updating the foo field across the wire or the entire shape document?)
我刚刚尝试过,并且能够通过将整个对象与新的和/或更新的字段一起发送来成功更新并且有效。我想知道驱动程序是否足够聪明,只能更新最小的更改子集,还是只是盲目地更新整个事情?(在下面的例子中,它只是更新了线路上的 foo 字段还是整个形状文档?)
Code:
代码:
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
采纳答案by Thilo
I wonder if the driver is smart enough to only update the smallest subset of changes or if it's just blindly updating the entire thing?
我想知道驱动程序是否足够聪明,只能更新最小的更改子集,还是只是盲目地更新整个事情?
No, if you use the "normal" update method, the whole object will be sent over the wire. I suspect that the database server itself will be clever enough to only update the necessary indexes (and not the ones that did not change), if possible (i.e. the object could be updated in place and did not have to be moved because it grew too much)
不,如果您使用“正常”更新方法,整个对象将通过网络发送。我怀疑如果可能的话,数据库服务器本身会足够聪明,只更新必要的索引(而不是那些没有改变的索引)(即对象可以就地更新并且不必因为它增长太多而移动)很多)
What you can do is use the "atomic update modifier" functions. The Java documentation is a bit light on them, but since the driver just transmits the JSON, the stuff from the non-Java tutorials should work, for example:
您可以做的是使用“原子更新修饰符”功能。Java 文档对它们有点了解,但由于驱动程序只传输 JSON,因此非 Java 教程中的内容应该可以工作,例如:
shapes.update((DBObject)JSON.parse( "{ 'foo' : 'bar'}"),
(DBObject) JSON.parse( "{ '$set' : { 'foo': 'bat'}}") );
回答by tim_yates
Found an example here, which seems to show the usage for the update call. So for your example, I believe something like this should work?
在这里找到了一个例子,它似乎显示了更新调用的用法。所以对于你的例子,我相信这样的事情应该有效?
// 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' ) ) )
Edit
编辑
You might be able to use a category to construct your BasicDBObjects in a more groovy way...
您也许可以使用类别以更常规的方式构建您的 BasicDBObjects...
Something like this might do it:
像这样的事情可能会做到:
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() )
}
I haven't tested this though...
虽然我没有测试过这个...
Edit 2
编辑 2
Actually, BasicDBObject is a Map, so you should be able to do:
实际上,BasicDBObject 是一个 Map,所以你应该能够做到:
mongo.shapes.update( shape2, [ '$set':[ 'foo', 'bat' ] ] as BasicDBObject )
without needing the builder
不需要建造者
回答by Arun A K
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);
Just use the above steps . You can change the details without affecting other items associated to the same key.
只需使用上述步骤。您可以更改详细信息,而不会影响与同一键关联的其他项目。
回答by ElStepherino
This answer uses the mongo shell, but shows how you can go deep into a JSON object structure to modify a specific field without overwriting the rest.
此答案使用 mongo shell,但展示了如何深入研究 JSON 对象结构以修改特定字段而不覆盖其余字段。
Given the JSON object in a collection called 'my_collection':
给定名为“my_collection”的集合中的 JSON 对象:
{
"_id" : ObjectId("50fdb2a73f7bc7a5acecc4f8"),
"data" : {
"list" : [ 0, 1, 2, 7, 4, 5 ],
"subobj" : {
"var_a":"valuea",
"var_b":"valueb"
}
}
}
To update 'var_b' , without overwriting anything else:
要更新 'var_b' ,而不覆盖其他任何内容:
db.my_collection.update({"_id":"50fdb2a73f7bc7a5acecc4f8"}, { "$set":{"data.subobj.var_b":"new_value"}})
To update the 3rd element in the array 'list' with value '99', without overwriting anything else:
要使用值 '99' 更新数组 'list' 中的第三个元素,而不覆盖任何其他元素:
db.my_collection.update({"_id":"50fdb2a73f7bc7a5acecc4f8"}, { "$set":{"data.list.2":"99"} } )
回答by user2164052
// update
// 更新
WriteResult usr = (WriteResult)mongoOperation.upsert(new Query(Criteria.where("name").is("till")),
Update.update("password", "jk45"), "collection");
System.out.println("updatedUser : " + usr );
回答by robjwilkins
A lot of the answers on this post are using older versions of the Mongo Java Driver. If you're using a newer version of the Java Driver (v3.0+) then the preferred method seems to be to use the Document object instead of the DBObject interface.
这篇文章的很多答案都使用旧版本的 Mongo Java 驱动程序。如果您使用的是较新版本的 Java Driver (v3.0+),那么首选方法似乎是使用 Document 对象而不是 DBObject 接口。
Here is an example:
下面是一个例子:
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);