7

I am running on Mongodb 3.6, with mongo driver 3.4.3 and spring data mongo 1.5.10. Below is the structure of my document

{
  "_id": 12345,
  "_class": "com.example.ProductRates",
  "rates": [
    {
      "productId": NumberInt(1234),
      "rate": 100.0,
      "rateCardId": NumberInt(1),
      "month": NumberInt(201801)
    },
    {
      "productId": NumberInt(1234),
      "rate": 200.0,
      "rateCardId": NumberInt(1),
      "month": NumberInt(201802)
    },
    {
      "productId": NumberInt(1234),
      "rate": 400.0,
      "rateCardId": NumberInt(2),
      "month": NumberInt(201803)
    },
    {
      "productId": NumberInt(1235),
      "rate": 500.0,
      "rateCardId": NumberInt(1),
      "month": NumberInt(201801)
    },
    {
      "productId": NumberInt(1235),
      "rate": 234,
      "rateCardId": NumberInt(2),
      "month": NumberInt(201803)
    }
  ]
}

am trying to do bulk update on the data as shown below

db.rates.update(
  { "_id" : 1234 },
  { $set: { "rates.$[item].rate": 200  } },
  { multi: true, 
   arrayFilters: [ { "item.rateCardId": {$in: [ 1, 2]} } ]
  }
)

Now and trying to convert this code to java. Below is the code i was able to achieve for a bulk update case. As expected the below query is updating all the document due to the usage of $[]. Am trying to figure out how to apply array filters here using positional array update operators (like $[one] ).

WriteResult wr = getMongoTemplate().updateMulti(
            new Query(where("rates.rateCardId").is(1234)),
            new Update().set("rates.$[].rate", 200),
            ProductRates.class);

Also I could not find enough tutorials or documentation that suggests how to apply all the complex mongo queries in Java. please suggest if there are any good books or tutorial i can refer to.

2
  • Try new Update().set("rates.$.rate", 200) Commented Apr 18, 2018 at 18:36
  • I did try that, but that updates only the first element. In my case have to update all the element that matches the criteria Commented Apr 18, 2018 at 19:18

2 Answers 2

10

That should be:

WriteResult wr = getMongoTemplate().updateMulti(
  new Query(where("rates.rateCardId").is(1234)),
  new Update().set("rates.$[item].rate", 200),
  new UpdateOptions()
    .arrayFilters(
      Arrays.asList( Filters.in("item.rateCardId",Arrays.asList(1,2)) )
    ), 
  ProductRates.class
);

You need to make sure the underlying Java Driver is a 3.6.x version or greater in order to have the arrayFilters() and likely even to support the addition of UpdateOptions()

Sign up to request clarification or add additional context in comments.

2 Comments

"Java Driver is a 3.6.x" - None of the Spring data 1.5.x versions support this. So is it mandatory to get upgraded to 2.x to use mongo 3.6 related features?
@Kumaran If you want MongoDB 3.6 features like arrayFilters then yes you must have a supporting driver. Spring Mongo versions prior to 2.x use deprecated interfaces that are marked for removal. Some quite possibly by the time MongoDB 4.x ships and driver updates are made again. See Driver Compatibility
2

I found Neil's answer useful in solving this problem, but I wanted to offer a slightly different call than the one in his code snippet.

getMongoTemplate().getCollection("ProductRates").updateMany(
    new Document().append("rates.rateCardId", 1234),
    new Document().append("$set", new Document().append("rates.$[item].rate", 200)),
    new UpdateOptions()
        .arrayFilters(
            Collections.singletonList( Filters.in("item.rateCardId",
                                                 Arrays.asList(1,2)) ))
);

1 Comment

I have a question. Is there a way to work with Objects? You just append Text but I need something like a BasicDBObject. I find your answer much better. Got a like!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.