web-dev-qa-db-de.com

Wie aktualisiere ich Dokumentfelder in Mongo DB mithilfe des Java-Treibers?

Verweise:

Mongo db ist noch ziemlich neu, aber ich versuche, einen Teil eines vorhandenen Dokuments in einer Sammlung zu aktualisieren ... Leider enthält der obige Link kein Aktualisierungsbeispiel.

Im Wesentlichen möchte ich nur in der Lage sein:

  1. Fügen Sie einem Dokument neue Felder hinzu
  2. Aktualisieren Sie vorhandene Felder eines Dokuments auf einen neuen Wert

Hier ist mein Code (Grails + Groovy + Java + MongoDB + der Java-Treiber):

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

Dadurch wird das gesamte Objekt ziemlich überlastet. Ich könnte versuchen, nur das ursprüngliche Formobjekt zu ändern und dann das Update darauf auszuführen. Aber bis dahin hat jemand Erfahrung damit, nur einzelne Felder (und nicht das gesamte Dokument) zu aktualisieren?

BEARBEITEN:

Ich habe es gerade ausprobiert und konnte erfolgreich aktualisieren, indem ich das gesamte Objekt mit neuen und/oder aktualisierten Feldern übersandte, und das funktioniert. Ich frage mich, ob der Treiber klug genug ist, nur die kleinste Teilmenge der Änderungen zu aktualisieren, oder ob er nur blind die gesamte Sache aktualisiert. (Im folgenden Fall wird nur das foo-Feld über die Leitung oder das gesamte Formdokument aktualisiert.)

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
18
longda

Ich frage mich, ob der Treiber intelligent genug ist, um nur die kleinste Teilmenge der Änderungen zu aktualisieren, oder ob er die gesamte Sache nur blind aktualisiert.

Nein, wenn Sie die "normale" Aktualisierungsmethode verwenden, wird das gesamte Objekt über die Leitung gesendet. Ich vermute, der Datenbankserver selbst ist schlau genug, nur die erforderlichen Indizes (und nicht die Indizes) zu aktualisieren nicht geändert), wenn möglich (dh das Objekt konnte an Ort und Stelle aktualisiert werden und musste nicht verschoben werden, da es zu stark gewachsen ist)

Sie können die "atomic update modifier" -Funktionen verwenden. Die Java-Dokumentation ist etwas hellhörig, aber da der Treiber nur die JSON überträgt, sollte das Zeug aus den Nicht-Java-Lernprogrammen funktionieren, zum Beispiel:

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

Fand hier ein Beispiel , das die Verwendung für den Aktualisierungsaufruf zu zeigen scheint. Also glaube ich, dass so etwas funktionieren sollte?

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

Bearbeiten

Sie können möglicherweise eine Kategorie verwenden, um Ihre BasicDBObjects auf eine groovigere Weise zu erstellen ...

So etwas könnte es tun:

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() )
}

Ich habe das allerdings nicht getestet ...

Bearbeiten 2

Eigentlich ist BasicDBObject eine Map, also sollten Sie folgendes können:

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

ohne den Erbauer zu benötigen

11
tim_yates

Viele Antworten in diesem Beitrag verwenden ältere Versionen des Mongo Java Driver. Wenn Sie eine neuere Version des Java-Treibers (v3.0 +) verwenden, scheint die bevorzugte Methode die Verwendung des Document-Objekts anstelle der DBObject-Schnittstelle zu sein.

Hier ist ein Beispiel:

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

Diese Antwort verwendet die Mongo-Shell, zeigt jedoch, wie Sie tief in eine JSON-Objektstruktur einsteigen können, um ein bestimmtes Feld zu ändern, ohne den Rest zu überschreiben.

Angenommen, das JSON-Objekt in einer Sammlung mit dem Namen 'my_collection':

{ 
  "_id" : ObjectId("50fdb2a73f7bc7a5acecc4f8"), 
  "data" : { 
    "list" : [ 0, 1, 2, 7, 4, 5 ], 
    "subobj" : { 
       "var_a":"valuea",
       "var_b":"valueb" 
     }
  }
}

'Var_b' aktualisieren, ohne etwas anderes zu überschreiben:

db.my_collection.update({"_id":"50fdb2a73f7bc7a5acecc4f8"}, { "$set":{"data.subobj.var_b":"new_value"}})

So aktualisieren Sie das 3. Element im Array 'list' mit dem Wert '99', ohne etwas anderes zu überschreiben:

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

Verwenden Sie einfach die obigen Schritte. Sie können die Details ändern, ohne andere Elemente zu beeinflussen, die demselben Schlüssel zugeordnet sind. 

1
Arun A K

// Update 

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

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

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