如何使用java驱动程序更新mongo db中的文档字段?

时间:2010-08-27 00:25:08

标签: java mongodb grails groovy mongo-java

参考文献:

mongo db还是新手,但我正在尝试更新集合中现有文档的一部分......遗憾的是,上面的链接没有更新示例。

基本上,我只想:

  1. 向文档添加新字段
  2. 更新文档的现有字段 一个新的值
  3. 这是我的代码(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
    

6 个答案:

答案 0 :(得分:12)

  

我想知道驱动程序是否足够聪明,只能更新最小的更改子集,或者只是盲目更新整个事物?

不,如果您使用“普通”更新方法,整个对象将通过网络发送。 我怀疑数据库服务器本身将足够聪明,只能更新必要的索引(而不是那些没有改变的索引),如果可能的话(即对象可以在适当的位置更新而不必移动,因为它也增长了多)

您可以使用“原子更新修饰符”功能。 Java文档对它们有点了解,但由于驱动程序只传输JSON,因此非Java教程中的内容应该可以工作,例如:

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

答案 1 :(得分:11)

找到了an example here,它似乎显示了更新调用的用法。那么对于你的例子,我相信这样的事情应该有效吗?

// 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是一个Map,所以你应该可以这样做:

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

不需要构建器

答案 2 :(得分:5)

这篇文章的很多答案都是使用旧版本的Mongo Java Driver。如果您使用的是较新版本的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);

答案 3 :(得分:3)

这个答案使用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"} } )

答案 4 :(得分:1)

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

只需使用上述步骤即可。您可以更改详细信息,而不会影响与同一密钥关联的其他项目。

答案 5 :(得分:0)

// update

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

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

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