1

Is there a way to achieve the following:-

MyDocument {
    String docId;
    Integer bal;
    Set<String> actions;
}
  1. I need to update the field actions with some value of a user action, say from

    [a1, a2]
    

    to

    [a1, a2, a3]
    
  2. At the same time, this added action can increment the bal by some value so I need to ensure that $inc operation is also implemented for the bal field.


One way of achieving this I could think of was incrementing the bal using one update query :

Bson searchFilter = Filters.in("docId", <someId>);

// couldn't find a cleaner way of increment in mongo-java
BasicDBObject modifiedObject = new BasicDBObject();
modifiedObject.put("$inc", new BasicDBObject().append("bal",2)); // any value to increment

mongoCollection.updateOne(searchFilter, modifiedObject);

I can thereafter execute another update document query for set of actions update.


Another way could possibly have been updating the documents with both the fields. For which :

  • I would have to find the document first, read the current bal, perform the compute at application.
  • Then update the document with both the computed fields.

In both the above approaches, I couldn't see a way of avoiding to query the DB twice. Is there any other workaround possible to achieve this currently?

Also, I am concerned about the atomicity with the above combination of [UPDATE + UPDATE] or [GET + UPDATE], given multiple such concurrent queries can occur, is the concern justified even?

Do let me know any further detail required.

Naman
  • 27,789
  • 26
  • 218
  • 353
  • So basically asking that where `a2` is already in the "set" then you don't want to increment `bal`. Right? – Neil Lunn May 28 '18 at 06:02
  • @NeilLunn The current question is more towards a new entry in the set. Redundant (not unique) would also be a use case though. – Naman May 28 '18 at 06:04
  • There's a difference, which I am asking you to clarify. Either you are asking. A. If `a2` is already in the set then don't add and don't increment. B. Add an item to the array, "maybe" as a set but **always** increment. Just trying to distill what you want to achieve into very simple terms. – Neil Lunn May 28 '18 at 06:06
  • @NeilLunn Sure, I understand your point. The current task I am looking to solve for is **B**. I would add to action set as well as increment the `bal` based on the action that I would be adding. – Naman May 28 '18 at 06:11
  • You an add multiple actions in an update without problem as long as they are not on the same path. Yours are not. Just in case you change your mind and decide you actually want **A**, then both duplicates show how to "conditionally" not update where an item is already present in the set. And the "likes voting" also demonstrates the basic principle of `$push` and `$inc`. – Neil Lunn May 28 '18 at 06:14
  • @NeilLunn Thanks for the links. I was exploring a similar combination of `$inc` and `$push` (just that with mongo-java-driver seems like I might have to build those `BasicDBObject`s). Though another complication was to determine the underflow and overflow of the `bal`. I would be doing an update with search filter based on a toggle sth. like `Filters.and(Filters.in("docId", ),Filters.lte("bal",maxBalance - balToAdd)); // overflow`. Which is where I believe [`UpdateResult`](http://mongodb.github.io/mongo-java-driver/3.5/javadoc/?com/mongodb/client/result/UpdateResult.html) shall help me. – Naman May 28 '18 at 07:20

0 Answers0