Bandolier2k
Bandolier2k

Reputation: 135

MongoDB Java Driver Update Sub-Document

I am trying to update a sub-document through MongoDB Java Driver.

I have the following structure in Mongo:

    {
        "_id" : "9999996978c9df5b02999999",
        "title" : "The Effects of Glaze on Pottery",
        "numberOfDownloads" : "453",
        "summary" : "This is a summary of the document",
        "documents" : {
                "file" : "99991F64C16E9A0954E89999",
                "mimetype" : "document/pdf",
                "pages" : "415",
                "downloads" : "453"
        }
}

And using the Java Driver I can update the root documents "numberOfDownloads" field just fine in this way:

        Document updDocQuery = new Document("_id", "9999996978c9df5b02999999");

        Document updDocValues = new Document("numberOfDownloads","555");

        Document updDocSet = new Document("$set",updDocValues);

        System.out.println(updDocSet.toJson());

        collection.updateOne(updDocQuery, updDocSet);

Which works fine.

Now I'm also trying to update the SubDocument "documents" to also set the "downloads" value to be the same - and I'm trying something like this:

        Document updDocQuery = new Document("_id", "9999996978c9df5b02999999");

        Document updDocValues = new Document("numberOfDownloads","555");

        Document updSubDocValues = new Document("downloads","555");

        updDocValues.append("documents", updSubDocValues);
        Document updDocSet = new Document("$set",updDocValues);

        System.out.println(updDocSet.toJson());

        collection.updateOne(updDocQuery, updDocSet);

Which is duly updating the "documents" attribute to my new value - but I want to update the specific field and leave the others intact.

I am ending up with a resulting document in Mongo of:

    {
        "_id" : "9999996978c9df5b02999999",
        "title" : "The Effects of Glaze on Pottery",
        "numberOfDownloads" : "555",
        "summary" : "This is a summary of the document",
        "documents" : {
                "downloads" : "555"
        }
}

And I need it to be:

    {
        "_id" : "9999996978c9df5b02999999",
        "title" : "The Effects of Glaze on Pottery",
        "numberOfDownloads" : "555",
        "summary" : "This is a summary of the document",
        "documents" : {
                "file" : "99991F64C16E9A0954E89999",
                "mimetype" : "document/pdf",
                "pages" : "415",
                "downloads" : "555"
        }
}

I'd prefer to not have to pull the record, convert it to an object, update the values and submit it for an update - but that seems inefficient.

I can execute this query from Mongo Console and it works great:

db.Paper.update(
    {"_id" : "5617776978c9df5b02f68228"},
    {$set: 
        { "numberOfDownloads" : "453", 
          "documents" : 
                { "downloads" : "453"}
        }
    });

Am I just missing something simple -or- am I terribly over-complicating this?

Upvotes: 1

Views: 3349

Answers (1)

Abdullah Rasheed
Abdullah Rasheed

Reputation: 3752

If this is the update set in mongodb:

 {$set: 
        { "numberOfDownloads" : "453", 
          "documents" : 
                { "downloads" : "453"}
        }
 }

You can use the Document class this way:

Document upDocValue = new Document("numberOfDownloads": "453")
                      .append("documents.downloads":"453");

This will give you:

{
  "numberOfDownloads": "453",
  "documents" : 
    { "downloads" : "453"}
}

Then you can create the outer document with:

Document upDocSet = new Document("$set",updDocValue);

This should give you:

{$set: 
      { "numberOfDownloads" : "453", 
            "documents" : 
                  { "downloads" : "453"}
      }
}

Then you run your query here:

collection.updateOne(upDocQuery,upDocSet);

So you eventually have:

Document updDocQuery = new Document("_id", "9999996978c9df5b02999999");

Document upDocValue = new Document("numberOfDownloads": "453")
                          .append("documents.downloads":"453");

Document upDocSet = new Document("$set",updDocValue);

collection.updateOne(upDocQuery,upDocSet);

Upvotes: 3

Related Questions