Erik L
Erik L

Reputation: 33

Remove document from array in MongoDB Java

I got a JSON string that looks something like this:

String tmp = "[
   {
      "ID":"12",
      "Date":"2018-02-02",
      "ObjData":[
         {
            "Name":"AAA",
            "Order":"12345",
            "Extra1":{
               "Temp":"3"
            },
            "Extra2":{
               "Temp":"5"
            }
         },
         {
            "Name":"BBB",
            "Order":"54321",
            "Extra1":{
               "Temp":"3"
            },
            "Extra2":{
               "Temp":"5"
            }
         }
      ]
   }
]"

I would like to remove for example the the document where ´Order´ equals "54321" from ´ObjData´. I got the following code:

Document doc = new Document();
doc = Document.parse(tmp);

Document fields = new Document("ID", "12")
    .append("ObjData", Arrays.asList(new Document("Order", "54321")));

Document update = new Document("$pull", fields);

coll.updateOne(doc, update);

I am trying to use the ´pull´ method to remove the entire document from the array where the ´Order´ equals 54321 but for some reason it's not working, I am probably doing something wrong. Could someone point out the issue please?

Also, what would be the best way to keep count of the documents within the array so that once all documents are pulled the entire document is deleted from the database? Would it be good to add some kind of ´size´ attribute and keep track of the size and decrease it after each pull?

Upvotes: 3

Views: 2348

Answers (2)

Brian
Brian

Reputation: 17299

Updating records to remove values from ObjData array

The first parameter to the updateOne method is a query to find the document you want to update, not the full document.

So for your code, assuming ID is a unique value and that there's an item in your collection with an ID of "12":

// { ID: "12" }
Document query = new Document("ID", "12");

// { ObjData: { $pull: { Order: "54321" } } }
Document update = new Document("ObjData",
        new Document("$pull",
                new Document("Order", "54321")
        )
);

coll.updateOne(query, update);

Alternatively, if you want to remove the order from all documents in the database, just replace query with an empty Document, i.e.:

// { <empty> }
Document query = new Document();

Deleting records with empty ObjData array

As for removing records when the size reaches zero, you can use a filter with $size:

db.myColl.deleteMany({ ObjData: { $size: 0 } })

This is also doable using the Java driver:

// { ObjData: { $size: 0 } }
Document query = new Document("ObjData",
        new Document("$size", 0)
);
coll.deleteMany(query);

Note that for large collections (i.e. where myColl is large, not the ObjData array), this may not perform very well. If this is the case, then you may want to track the size separately (as you hinted at in your question) and index it to make it faster to search on since you can't create an index on array size in MongoDB.

References

Upvotes: 1

Yuriy Alevohin
Yuriy Alevohin

Reputation: 934

To remove document with Order=54321 from internal array from any document (if you don't know ID) you can use empty filter like:

    Document filter = new Document();
    Document update = new Document("$pull", new Document("ObjData", new Document("Order", "54321")));

    coll.updateOne(filter, update);

Upvotes: 1

Related Questions