18

参考文献:

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

これにより、オブジェクト全体がかなり破壊されます...元の形状オブジェクトを変更してから、その上で更新を実行してみてください。しかしそれまで、(文書全体ではなく) 個々のフィールドだけを更新した経験のある人はいますか?

編集:

試してみたところ、オブジェクト全体を新しいフィールドや更新されたフィールドで送信することで正常に更新できましたが、それは機能します。ドライバーは変更の最小サブセットのみを更新するほどスマートなのか、それともやみくもに全体を更新しているだけなのか? (以下のケースでは、回線を介して 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
4

6 に答える 6

12

ドライバーは変更の最小サブセットのみを更新するほどスマートなのか、それともやみくもに全体を更新しているだけなのか?

いいえ、「通常の」更新方法を使用すると、オブジェクト全体がネットワーク経由で送信されます。データベースサーバー自体は、可能であれば必要なインデックスのみを更新する(変更されていないインデックスは更新しない)ほど賢いと思います(つまり、オブジェクトはその場で更新でき、大きくなりすぎたために移動する必要はありませんでした)多くの)

できることは、「アトミック更新修飾子」関数を使用することです。Java のドキュメントはそれらについて少し軽視していますが、ドライバーは JSON を送信するだけなので、Java 以外のチュートリアルのものは機能するはずです。たとえば、次のようになります。

shapes.update((DBObject)JSON.parse(    "{ 'foo' : 'bar'}"),  
    (DBObject) JSON.parse(          "{ '$set' : { 'foo': 'bat'}}")   );
于 2010-08-27T08:46:31.473 に答える
11

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

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

ビルダーを必要とせずに

于 2010-08-27T08:45:23.333 に答える
6

この投稿の回答の多くは、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);
于 2016-01-18T15:58:23.000 に答える
3

この回答ではmongoシェルを使用していますが、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"} } )
于 2013-01-21T22:45:47.033 に答える
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);

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

于 2012-08-24T05:06:16.750 に答える
0

// アップデート

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

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

System.out.println("updatedUser : " + usr );
于 2013-03-25T09:35:55.450 に答える