MongoDB has vast support for arrays but syntax seems to be complicated at first glance. Performing array operations using MongoDB Java driver abstractions is a bit trickier.
Here is official MongoDB Array Update operations tutorial, it describes how array operations should be executed at MongoDB shell.
All examples provided in this article are valid and tested with org.mongodb:mongodb-driver:3.9.1 library. Here is the doc
In every example given below I will use MongoCollection<Document> collection
object instantiated like this:
MongoCollection<Document> collection = MongoClients .create("mongodb://127.0.0.1:27017") .getDatabase("myDb") .getCollection("myCollection");
Simple add (push) element at the end of the array
// { "_id" : 1 } or { "_id" : 1, "arr" : [ ] } collection.updateOne( Filters.eq("_id", 1), new Document().append( "$push", new Document("arr", new Document("v", 1)) ) ); // { "_id" : 1, "arr" : [ { "v" : 1 } ] }
It’s an equivalent of following MongoDB shell operation:
db.myCollection.updateOne( { "_id" : 1 }, { "$push" : { "arr" : { "v" : 1 } } } );
Add (push) multiple elements at the end of the array
With $each modifier you can add several elements into the array inside one query.
// { "_id" : 1, "arr" : [ { "v" : 1 } ] } collection.updateOne( Filters.eq("_id", 1), Updates.pushEach("arr", Arrays.asList(new Document("v", 2), new Document("v", 3)) ) ); // { "_id" : 1, "arr" : [ { "v" : 1 }, { "v" : 2 }, { "v" : 3 } ] }
Equivalent MongoDB shell query
db.myCollection.updateOne( { "_id" : 1 }, { "$push" : { "arr" : { "$each" : [ { "v" : 2 }, { "v" : 3 } ] } } } );
Add (push) multiple elements at the specific position in the array
Here comes $position modifier, intended to specify where first element of $each value should be placed. If this position is already occupied the existing item would be shifted. Positions are numerated starting from 0.
// { "_id" : 1, "arr" : [ { "v" : 1 } ] } collection.updateOne( Filters.eq("_id", 1), Updates.pushEach("arr", Arrays.asList(new Document("v", 2), new Document("v", 3)), new PushOptions().position(0) ) ); // { "_id" : 1, "arr" : [ { "v" : 2 }, { "v" : 3 }, { "v" : 1 } ] }
Equivalent MongoDB shell query
db.myCollection.updateOne( { "_id" : 1 }, { "$push" : { "arr" : { "$each" : [ { "v" : 2 }, { "v" : 3 } ], "$position" : 0 } } } );
Passing negative value with $position modifier adds elements at position from the end of the array. Think of this as numeration change from right to left. E.g. $position: -1 will place $each elements in natural order just before the last element in a document.
// { "_id" : 1, "arr" : [ { "v" : 2 }, { "v" : 3 }, { "v" : 1 } ] } collection.updateOne( Filters.eq("_id", 1), Updates.pushEach("arr", Arrays.asList(new Document("v", 4), new Document("v", 5)), new PushOptions().position(-1) ) ); // { "_id" : 1, "arr" : [ { "v" : 2 }, { "v" : 3 }, { "v" : 4 }, { "v" : 5 }, { "v" : 1 } ] }
Add elements keeping the array sorted
Depending on the data stored in the array – it may be very useful to keep it sorted. Nice thing that array could be kept sorted for all your subsequent reads if you sort it when adding new values.
// { "_id" : 1, "arr" : [ { "v" : 5 }, { "v" : 2 } ] } collection.updateOne( Filters.eq("_id", 1), Updates.pushEach("arr", Arrays.asList(new Document("v", 3), new Document("v", 1)), new PushOptions().sortDocument(new Document("v", 1))) ) ); // { "_id" : 1, "arr" : [ { "v" : 1 }, { "v" : 2 }, { "v" : 3 }, { "v" : 5 } ] }
new PushOptions().sortDocument(new Document(“v”, 1))) – specifies that sorting should be done by “v” field in ascending order.
Pass new Document(“v”, -1) to achieve sorting by “v” field in descending order.
If you store in the array primitive values (like [ 3, 17, 9 ]) instead of documents. Then pass new PushOptions().sort(1) to sort them according to their natural ascending order or new PushOptions().sort(-1) for descending.
Equivalent MongoDB shell query
db.myCollection.updateOne( { "_id" : 1 }, { "$push" : { "arr" : { "$each" : [ { "v" : 3 }, { "v" : 1 } ], "$sort": { "v" : 1 } } } } );
Add and keep limited number of elements in sorted array
$slice modifier limits the resulting array after applying $push operator with $each modifier. Note that $slice may be used only with $each modifier.
This code will first add documents {“v” : 7} and {“v” : 0} then sort the array by “v” field in ascending order and after that shrink the array down to 3 first elements and store it.
// { "_id" : 1, "arr" : [ { "v" : 1 }, { "v" : 2 }, { "v" : 3 }, { "v" : 5 } ] } collection.updateOne( Filters.eq("_id", 1), Updates.pushEach("arr", Arrays.asList(new Document("v": 7), new Document("v": 0)), new PushOptions().sortDocument(new Document("v", 1))).slice(3) ) ); // { "_id" : 1, "arr" : [ { "v" : 0 }, { "v" : 1 }, { "v" : 2 } ] }
Equivalent MongoDB shell query
db.myCollection.updateOne( { "_id" : 1 }, { "$push" : { "arr" : { "$each" : [ { "v" : 7 }, { "v" : 0 } ], "$sort": { "v" : 1 }, "$slice": 3 } } } );
All MongoDB Java driver and MongoDB shell query examples are thoroughly tested before posting.