web-dev-qa-db-ja.com

Javaドライバを使用してmongo dbのドキュメントのフィールドを更新するにはどうすればよいですか?

参照:

Mongo dbはまだ新しいですが、コレクション内の既存のドキュメントの一部を更新しようとしています...残念ながら、上のリンクには更新の例がありません。

基本的に、私は次のことができるようにしたいだけです。

  1. ドキュメントに新しいフィールドを追加する
  2. ドキュメントの既存のフィールドを新しい値に更新する

これが私のコードです(Grails + Groovy + Java + MongoDB + Java driver)):

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
longda

ドライバーが変更の最小のサブセットのみを更新するのに十分スマートであるか、それとも全体を盲目的に更新しているだけなのだろうか?

いいえ、「通常の」更新メソッドを使用すると、オブジェクト全体がネットワーク経由で送信されます。データベースサーバー自体は、必要に応じて(変更されていないインデックスではなく)必要なインデックスのみを更新するのに十分な能力があると思います(つまり、オブジェクトは適切に更新でき、オブジェクトも大きくなったため移動する必要はありませんでした)多く)

あなたができることは、「アトミック更新修飾子」関数を使用することです。 Javaドキュメンテーションはそれらの少し軽いですが、ドライバーはJSONを送信するだけなので、非Javaチュートリアルからのものは動作するはずです。例えば:

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

見つかりました ここの例 。これは、更新呼び出しの使用法を示しているようです。あなたの例として、私はこのようなものがうまくいくと思いますか?

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

ビルダーを必要とせずに

11
tim_yates

この投稿の回答の多くは、古いバージョンのMongo Java Driverを使用しています。新しいバージョンのJava Driver(v3 .0+)の場合、推奨される方法は、DBObjectインターフェイスではなくDocumentオブジェクトを使用することです。

次に例を示します。

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

この回答は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"}})

配列 'list'の3番目の要素を、値 '99'で更新します。それ以外は上書きしません。

db.my_collection.update({"_id":"50fdb2a73f7bc7a5acecc4f8"}, { "$set":{"data.list.2":"99"} } )
3
ElStepherino
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);

上記の手順を使用してください。同じキーに関連付けられている他のアイテムに影響を与えることなく、詳細を変更できます。

1
Arun A K

//更新

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

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

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