Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB,using java to update three fields of document at the same time,sometimes only two fields is updated

Tags:

java

mongodb

//get the collection
DBCollection coll = MongoDBClient.getInstance().getAlarmInfoCollection();

DBObject query = new BasicDBObject();
query.put(aa, "51d2b09f81b8a943f9e825aa");

DBObject update = new BasicDBObject();
DBObject history = new BasicDBObject();
history.put("ishistory", 1);
history.put("acknowledged", 1);
history.put("state", 1);        
update.put("$set", history);
coll.updateMulti(query, update);

using the program before to update the document in mongodb,but sometimes it can sucess,sometimes it only update two fields(the field, "state", is not updated), and the propram did not report any error. Is there any mistake in my program?

like image 294
user2545818 Avatar asked Jul 03 '13 09:07

user2545818


People also ask

How do you update a specific field in MongoDB?

To update a single field or specific fields just use the $set operator. This will update a specific field of "citiName" by value "Jakarta Pusat" that defined by $set operator.


1 Answers

I've written a unit test to show how the code behaves. This unit test proves that:

  1. you should be able to update more than one field at once (i.e. multiple fields can be updated with the $set keyword)
  2. updateMulti will update all matching documents

(Note, like all Java MongoDB tests this uses TestNG not JUnit, but it's pretty similar in this case)

@Test
public void shouldUpdateAllMatchingFieldsUsingMultiUpdate() throws UnknownHostException {
    MongoClient mongoClient = new MongoClient();
    DB db = mongoClient.getDB("myDatabase");
    DBCollection coll = db.getCollection("coll");
    coll.drop();

    //Put some test data in the database
    for (int i = 0; i < 5; i++) {
        DBObject value = new BasicDBObject();
        value.put("fieldToQuery", "a");
        value.put("ishistory", 2+i);
        value.put("acknowledged", 3+i);
        value.put("state", 14+i);
        value.put("someOtherArbitraryField", Math.random() * 1000);
        System.out.println(value);
        coll.insert(value);
    }

    DBObject query = new BasicDBObject("fieldToQuery", "a");

    DBObject history = new BasicDBObject().append("ishistory", 1)
                                          .append("acknowledged", 1)
                                          .append("state", 1);

    DBObject update = new BasicDBObject("$set", history);

    //This syntax for update means that all three fields will be set to the new given value
    Assert.assertEquals(update.toString(), "{ \"$set\" : { \"ishistory\" : 1 , \"acknowledged\" : 1 , \"state\" : 1}}");

    //Do the update, updating every document that matches the query
    coll.updateMulti(query, update);

    //find The new values
    DBCursor updatedDocuments = coll.find(query);
    for (DBObject updatedDocument : updatedDocuments) {
        Assert.assertEquals(updatedDocument.get("ishistory"), 1);
        Assert.assertEquals(updatedDocument.get("acknowledged"), 1);
        Assert.assertEquals(updatedDocument.get("state"), 1);
        System.out.println(updatedDocument);
    }
}

This test passes. For an example run, the data in the database is:

{ "fieldToQuery" : "a" , "ishistory" : 2 , "acknowledged" : 3 , "state" : 14 , "someOtherArbitraryField" : 700.7831275035031}
{ "fieldToQuery" : "a" , "ishistory" : 3 , "acknowledged" : 4 , "state" : 15 , "someOtherArbitraryField" : 72.65538582882736}
{ "fieldToQuery" : "a" , "ishistory" : 4 , "acknowledged" : 5 , "state" : 16 , "someOtherArbitraryField" : 980.0065367659304}
{ "fieldToQuery" : "a" , "ishistory" : 5 , "acknowledged" : 6 , "state" : 17 , "someOtherArbitraryField" : 91.58266286854722}
{ "fieldToQuery" : "a" , "ishistory" : 6 , "acknowledged" : 7 , "state" : 18 , "someOtherArbitraryField" : 448.19176202797115}

At the end of the test, after updateMulti is called with the $set operator, the documents in the database are:

{ "fieldToQuery" : "a" , "ishistory" : 1 , "acknowledged" : 1 , "state" : 1 , "someOtherArbitraryField" : 700.7831275035031}
{ "fieldToQuery" : "a" , "ishistory" : 1 , "acknowledged" : 1 , "state" : 1 , "someOtherArbitraryField" : 72.65538582882736}
{ "fieldToQuery" : "a" , "ishistory" : 1 , "acknowledged" : 1 , "state" : 1 , "someOtherArbitraryField" : 980.0065367659304}
{ "fieldToQuery" : "a" , "ishistory" : 1 , "acknowledged" : 1 , "state" : 1 , "someOtherArbitraryField" : 91.58266286854722}
{ "fieldToQuery" : "a" , "ishistory" : 1 , "acknowledged" : 1 , "state" : 1 , "someOtherArbitraryField" : 448.19176202797115}

So the update has worked, setting the three fields to 1 for all matching documents, not touching any of the other data on the document.

It might be worth noting that my syntax for setting query, update and history is a little more readable and bit shorter, although it should be doing the same thing as the code in the original question:

DBObject query = new BasicDBObject("fieldToQuery", "a");

DBObject history = new BasicDBObject().append("ishistory", 1)
                                      .append("acknowledged", 1)
                                      .append("state", 1);

DBObject update = new BasicDBObject("$set", history);

Am I correct in assuming that you want all records that match your query to be updated with the given values? Hence your use of updateMulti?

like image 118
Trisha Avatar answered Sep 21 '22 00:09

Trisha