0

I am using below mongo aggregation pipeline in spring boot java to update document in mongodb. Below is the raw mongo query that works fine when executed directly on mongodb

    db.lock.aggregate([
  {
    "$project": {
      "_id": 1,
      "ownerId": 1,
      "releaseTs": 1,
      "auditCreateTs": 1,
      "auditUpdateTs": 1,
      "difference": {
        "$divide": [
          {
            "$subtract": [
              new Date(),
              "$releaseTs"
            ]
          },
          1000
        ]
      }
    }
  },
  {
    "$match": {
      "$and": [
        {
          "_id": "magpie"
        },
        {
          "$or": [
            {
              "ownerId": "reena"
            },
            {
              "difference": {
                "$gt": 10
              }
            }
          ]
        }
      ]
    }
  },
  {
    "$set": {
      "ownerId": "Jivii"
    }
  },
  {
    "$merge": {
      into: "lock",
      on: [
        "_id"
      ],
      // Optional
      whenMatched: "replace",
      // Optional
      whenNotMatched: "discard"// Optional
      
    }
  }
])

I have tried to convert above query in java, but facing below issues with java code:

  • Match criteria is not working (involves use of $or and $and operator), so the actual documents are not updated in mongodb collection.
  • Is there any way to get the count of documents updated when this aggregate function is executed?

I am writing match criteria condition here in simple language, so someone can help to point what's wrong in below aggregation query.

Update the document where _id is "x101" AND (OwnerId = "testUser1" OR Difference between current_timestamp ,releaseTs is greater than certain value)

    //Get the time difference in seconds
    String jsonExpression = "{\"$divide\": [{\"$subtract\":[new ISODate(),\"$releaseTs\"]},1000]}";
    AggregationOperation project = Aggregation.project().andInclude("_id","ownerId", "releaseTs", "auditCreateTs","auditUpdateTs").and(context -> context.getMappedObject(Document.parse(jsonExpression))).as("difference");
    Criteria firstCond = Criteria.where("_id").is("x101");
    Criteria secondOrCond = new Criteria().orOperator(
                Criteria.where("ownerId​").is("testUser1").and("difference").gt(lockTimeoutInSecs));
    AggregationOperation match  = Aggregation.match(new Criteria().andOperator(firstCond,secondOrCond));
    AddFieldsOperation update = Aggregation.addFields().addFieldWithValue("ownerId", ownerId).addFieldWithValue("releaseTs", now.plusSeconds(lockTimeoutInSecs))
    .addFieldWithValue("auditUpdateTs", now).build();
    MergeOperation merge = Aggregation.merge().id(UniqueMergeId.id()).intoCollection("lock").build();
    List<AggregationOperation> aggOps = new ArrayList<>();
    aggOps.add(project);
    aggOps.add(match);
    aggOps.add(update);
    aggOps.add(merge);
    Aggregation aggregation = Aggregation.newAggregation(aggOps);
    int count = mongoTemplate.aggregate(aggregation, Lock.class, Lock.class).getMappedResults().size();

Mongodb version is 5.0.2, driver version is 4.2

8
  • Does spring provide a method to print the aggregation pipeline as JSON? Commented Jan 5, 2024 at 11:00
  • 3
    as first step, I would suggest finding the raw mql query that works for you for example here: mongoplayground.net, then you will need to only convert it into spring syntax Commented Jan 5, 2024 at 11:13
  • @dododo I have updated the raw mongo query, it works fine. But when I converted it to spring java syntax, it not performing the update operation on collection. Commented Jan 5, 2024 at 15:22
  • @dododo mongoplayground.net/p/QybMvaZnMH Commented Jan 5, 2024 at 15:28
  • the link is broken Commented Jan 5, 2024 at 16:40

0

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.