[Java SpringBoot] How to update a document on condition

Hi there,

I’m working on a SpringBoot Java project, and I would like to update a document only on a certain condition :

{
	factory: {
		workers: ["String"], 
		testers: ["String"], 
		developpers: ["String"], 
		status : String 
	}
}

I would like to update the factory’s status only if the size of (developers + testers) equal or greater than workers size, is this possible using mongoOperations ? if so I believe I need to use aggregations right ? because according to this doc, aggregations are used only to sort data (I’m not familiare with them).

The correct format of my structure is :

{
	factory: {
	   id: mongoId
		workers: ["String"], 
		testers: ["String"], 
		developpers: ["String"], 
		status : String 
	}
}

Hi @KamelA,

Can you please provide a bunch of example docs that I can insert easily and the expected updates on these documents once your query is done? This would help figure out what you are trying to do exactly and what’s the best approach before trying to find a solution for the Spring Boot part. Let’s find the MongoDB query first and then we can try to “translate it” in Java / Spring Boot eventually.

Cheers,
Maxime.

1 Like

Hi thanks for the reply, here’s the initial doc :

[
  {
    name: "factory",
    num: 3,
    workers: [
      "a",
      "b",
      "c"
    ],
    testers: [
      "a",
      
    ],
    developers: [
      "c"
    ],
    status: "NOT_FULL"
  }
]

And what I would like once, I add an element inside the array “testers” (for example), with mongo will compare the length of (developers + testers) with workers, and if it’s equal, mongo change the status to “FULL”, so the final result will be :


[
  {
    name: "factory",
    num: 3,
    workers: [
      "a",
      "b",
      "c"
    ],
    testers: [
      "a",
      "b",
      
    ],
    developers: [
      "c"
    ],
    status: "FULL"
  }
]

So the operation will be a mix of (findAndModify (to find the doc and add the element to an array) + comparaison of arrays size, then update the status if the the condition is met.

Greetings.

1 Like

Hi @KamelA,

Let’s say I have these 2 docs in my collections:

[
  {
    _id: ObjectId("6214d7d015bfcf433d5b7d33"),
    name: 'factory',
    num: 3,
    workers: [ 'a', 'b', 'c' ],
    testers: [ 'a', 'b' ],
    developers: [ 'c' ],
    status: 'NOT_FULL'
  },
  {
    _id: ObjectId("6214d7ed15bfcf433d5b7d34"),
    name: 'factory',
    num: 3,
    workers: [ 'a', 'b', 'c' ],
    testers: [ 'a' ],
    developers: [ 'c' ],
    status: 'NOT_FULL'
  }
]

The first one needs a status update.

We can do it like this:

db.coll.updateMany({
  status: {$ne: "FULL"},
  $expr: { $eq: [
    {$size: "$workers"}, 
    {$add: [{$size: "$testers"}, {$size: "$developers"}]}
  ]}
},
{$set: {status: "FULL"}})

Which would work better if the status field was indexed.
This query would also be faster if the array sizes were stored (and indexed) instead of being re-calculated all the time.
It’s usually fairly easy to maintain the size of the array and the array in sync by using in the same update operation $push or $pop for the array and $inc for the size.

Cheers,
Maxime.

1 Like

Thank you very much, this is exactly what I’m looking for, I will try now to translate this to a java spring query.

Apparently the expression $expr is not well supported on spring-mongodb : https://github.com/spring-projects/spring-data-mongodb/issues/3587 so I think for now, I will use BasicQuery and use directly the query you gave me, thank you.

I have problem finding the added value in Spring Boot to be honest.

I did my own little starter project for people who are starting a project with Spring Boot here. But in my opinion it makes things more complicated than just using the MongoDB Java Driver…

I like the fact that interfaces are auto implemented… But in real life, you never use the CRUD APIs out of the box like this. You do custom queries like this one and it doesn’t make you save time. In the end you have an extra proxy between you and the MongoDB Driver (which is still used in the backstage) so…

Yeah, I’m not a fan. But a solid demo could as well change my mind perhaps.

Cheers,
Maxime.

3 Likes

I feel the same. That why I call them, this and mongoose, obstruction layer rather than abstraction layer.

One of the selling point of mongo is that they do not impose a schema. You could, but that would be another obstruction layer. For the same reason, I do not use query builders in Java. With my query in native json, I can have the same query, sometimes stored in a file, be used in all nodejs, mongosh, java, … with the help of parse().

2 Likes

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.