Search code examples
javamongodbmongodb-java

$set and positional operator doesn't work in Java?


I have the following document in MongoDb collection called hosts

{ "_id"   : ObjectId("532aeec040a83df82181ff3c"), 
   "os"   : "WINDOWS", 
   "name" : "Host 1", 
   "bas" : [     
              {   "wwn" : "EE:00:11:FF",  "id" : "1" },   
              {   "wwn" : "AA:00:11:BB",  "id" : "2" } ] 
}

Now I want to update ba of id=1 in Host of name=Host 1 to { "wwn" : "AA:BB:CC:DD", "id" : "11" }. After the update the result will be

{ "_id"   : ObjectId("532aeec040a83df82181ff3c"), 
   "os"   : "WINDOWS", 
   "name" : "Host 1", 
   "bas" : [     
              {   "wwn" : "AA:BB:CC:DD",  "id" : "11" },   
              {   "wwn" : "AA:00:11:BB",  "id" : "2" } ] 
}

For this I used the mongo shell command

db.hosts.update( { name : "Host 1", "bas.id" : "1" }, 
 { "$set" : { "bas.$" : { wwn : "AA:BB:CC:DD", id : "11"} }} );

which worked great. Now I wanted to do the same using Java drivers and here is my code

BasicDBObject example = new BasicDBObject("name", "Host 1").append("bas\uff0eid", "1");
BasicDBObject newValue = new BasicDBObject("\u0024set",  new BasicDBObject("bas\uff0e\u0024", new BasicDBObject().append("wwn", "AA:BB:CC:DD).append("id","11")) ;
collection.update(example, newValue);

In the above code I had to replace . with \uff0 and $ with \u0024 to avoid exception being thrown. This update call is not updating the collection. When I inspected the BasicDBObject.toString() the JSON were same as what I had typed on console. Please help me.


Solution

  • I don't understand why you should need to write $ and . as Unicode escapes. I tried running your code with the actual characters in them and it worked fine with the 2.11 Java driver.

    But your code has two problems: 1) the full stop . is \u002e, not \uff0e, which is a very different character. 2) the syntax of the last part of the statement is not correct, but that is probably a copying error.

    Here's the code that I used, and it worked fine (I only created the objects and didn't actually run it against the database but I don't see why that wouldn't work).

        BasicDBObject example = new BasicDBObject("name", "Host 1").append("bas.id", "1");
        BasicDBObject newValue = new BasicDBObject("$set",
                                   new BasicDBObject("bas.$",
                                     new BasicDBObject()
                                       .append("wwn", "AA:BB:CC:DD").append("id","11"))) ;