Mongo collection named persons1 contains the following data:
db.persons1.find().pretty();
{ "_id" : "Sims", "count" : 32 }
{ "_id" : "Autumn", "count" : 35 }
{ "_id" : "Becker", "count" : 35 }
{ "_id" : "Cecile", "count" : 40 }
{ "_id" : "Poole", "count" : 32 }
{ "_id" : "Nanette", "count" : 31 }
Now through Java I have written the code to increment the count for the users which are present in the list
MongoClient mongoclient = new MongoClient("localhost", 27017);
MongoDatabase db = mongoclient.getDatabase("testdb1");
MongoCollection<Document> collection = db.getCollection("persons1");
List li = new ArrayList();
li.add("Sims");
li.add("Autumn");
collection.updateMany(
in("_id",li),
new Document("$inc", new Document("count", 1)),
new UpdateOptions().upsert(true));
After I run the above java program my output was as below.
db.persons1.find().pretty();
{ "_id" : "Sims", "count" : 33 }
{ "_id" : "Autumn", "count" : 36 }
{ "_id" : "Becker", "count" : 35 }
{ "_id" : "Cecile", "count" : 40 }
{ "_id" : "Poole", "count" : 32 }
{ "_id" : "Nanette", "count" : 31 }
My question: Is it possible to Insert and start the count from 1, for the entry present in the Array list and not present in the persons1 Collection?
Problem Description:
Before Program database contains details as follows:
{ "_id" : "Sims", "count" : 33 }
{ "_id" : "Autumn", "count" : 36 }
{ "_id" : "Becker", "count" : 35 }
{ "_id" : "Cecile", "count" : 40 }
{ "_id" : "Poole", "count" : 32 }
{ "_id" : "Nanette", "count" : 31 }
Sample Java code:
MongoClient mongoclient = new MongoClient("localhost", 27017);
MongoDatabase db = mongoclient.getDatabase("testdb1");
MongoCollection<Document> collection = db.getCollection("persons1");
List li = new ArrayList();
// Entry already Present so required to increment by 1
li.add("Sims");
// Entry already Present so required to increment by 1
li.add("Autumn");
// Entry is NOT Present, hence insert into persons data base with "_id" as User1 and count as 1
li.add("User1");
// Entry is NOT Present, hence insert into persons data base with "_id" as User1 and count as 1
li.add("User2");
// Code to be written
What should be the code to get the out put from the database as shown below:
{ "_id" : "Sims", "count" : 34 } // Entry already Present, incremented by 1
{ "_id" : "Autumn", "count" : 37 } // Entry already Present, incremented by 1
{ "_id" : "Becker", "count" : 35 }
{ "_id" : "Cecile", "count" : 40 }
{ "_id" : "Poole", "count" : 32 }
{ "_id" : "Nanette", "count" : 31 }
{ "_id" : "User1", "count" : 1 } // Entry Not Present, start by 1
{ "_id" : "User2", "count" : 1 } // Entry Not Present, start by 1
Here in MongoDB, the upsert option is a Boolean value. Suppose the value is true and the documents match the specified query filter. In that case, the applied update operation will update the documents. If the value is true and no documents match the condition, this option inserts a new document into the collection.
insert() provides no upsert possibility.
The updateMany() method updates all the documents in MongoDB collections that match the given query. When you update your document, the value of the _id field remains unchanged. This method can also add new fields in the document.
The "catch" here is that $in
arguments to _id
will not be interpreted as a valid "filler" for the _id
field within an "multi" flagged update, which is what you are doing. All the _id
values will be populated by default ObjectId
values instead on "upsert".
The way around this is to use "Bulk" operations, and with the Java 3.x driver you use the BulkWrite
class and a construction like this:
MongoCollection<Document> collection = db.getCollection("persons1");
List li = new ArrayList();
li.add("Sims");
li.add("User2");
List<WriteModel<Document>> updates = new ArrayList<WriteModel<Document>>();
ListIterator listIterator = li.listIterator();
while ( listIterator.hasNext() ) {
updates.add(
new UpdateOneModel<Document>(
new Document("_id",listIterator.next()),
new Document("$inc",new Document("count",1)),
new UpdateOptions().upsert(true)
)
);
}
BulkWriteResult bulkWriteResult = collection.bulkWrite(updates);
That manipulates your basic List
into UpdateOneModel
objects with a list that is suitable for bulkWrite
, and all "individual" updates are sent in the one request with the one response, even though they are "technically" mulitple update statements.
This is the only way that is valid to set multiple _id
keys or matches via $in
in general with update operations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With