Need help to write a updateOne syntax for my schema

Hi

My schema is like below

{
       name : "A",
	outerArr : [
		{
			outerId : 1,
			innerArr : [
				{
					 { date: '2023-08-1', type: 'Normal'},
					 { date: '2023-08-2', type: 'Normal'},
					 { date: '2023-08-3', type: 'Normal'}
				}
			]
		},
		{
			outerId : 2,
			innerArr : [
				{
					 { date: '2023-08-1', type: 'Normal'},
					 { date: '2023-08-2', type: 'Normal'},
					 { date: '2023-08-3', type: 'Normal'}
				}
			]
		},
		{
			outerId : 3,
			innerArr : [
				{
					 { date: '2023-08-1', type: 'Normal'},
					 { date: '2023-08-2', type: 'Normal'},
					 { date: '2023-08-3', type: 'Normal'}
				}
			]
		}
	]
}

I want to update multiple sub documents provided in outerId list [1, 2, 3 ] in a document A in a atomic fashion. Either all mentioned outerId should be modified or none.

Hep me to write a update command to change type to “Reserved” for a given date. “2023-08-3” to each of outerId in list.

I have tried

db.xyz.updateOne(
  {
    $and: [
      {"name" : "A"},
      { "outerArr.outerId": { $in: [1, 2, 3] } },
      { "outerArr.innerArr.date": "2023-08-3" },
      { "outerArr.innerArr.type": "Normal" }
    ]
  },
  {
    "$set": {
      "outerArr.$[i].innerArr.$[j].type": "Reserved"
    }
  },
  {
    "arrayFilters": [
      { 
        "outerArr.outerId": { "$in": [1, 2, 3] }
        
      },
      {
         "innerArr.date": "2023-08-3"
      }
    ]
  }
)

However this command fails if json is like below. The problem is outerId 2 and 3 matches conditions but not outerId 1. Write should have failed because outerId 1 not matching the query (My expectation), but when i run write succeeds.
How to make it work for outerId 1 AND outerId 2 AND outerId 3 (logical AND among each outerId in list)

{
	outerArr : [
		{
			outerId : 1,
			innerArr : [
				{
					 { date: '2023-08-1', type: 'Normal'},
					 { date: '2023-08-2', type: 'Normal'},
					 { date: '2023-08-3', type: 'Reserved'}
				}
			]
		},
		{
			outerId : 2,
			innerArr : [
				{
					 { date: '2023-08-1', type: 'Normal'},
					 { date: '2023-08-2', type: 'Normal'},
					 { date: '2023-08-3', type: 'Normal'}
				}
			]
		},
		{
			outerId : 3,
			innerArr : [
				{
					 { date: '2023-08-1', type: 'Normal'},
					 { date: '2023-08-2', type: 'Normal'},
					 { date: '2023-08-3', type: 'Normal'}
				}
			]
		}
	]
}

Please help in writing proper update

Hello @Manjunath_k_s,

The $in operator returns true if the value of the field matches any of the values from the array, same as $or condition,

You can try $all and $elemMatch operators, but you need to specify the separate condition for each outerId.

  • $all operator checks all the provided criteria should match
  • $elemMatch operator checks the provided criteria in each element
  • Here I have created a variable innerArr to reuse the condition.
const innerArr = {
  "$elemMatch": {
    "date": "2023-08-3",
    "type": "Normal"
  }
};
db.xyz.updateOne(
  {
    "name": "A",
    "outerArr": {
      "$all": [
        {
          "$elemMatch": {
            "outerId": 1,
            "innerArr": innerArr
          }
        },
        {
          "$elemMatch": {
            "outerId": 2,
            "innerArr": innerArr
          }
        },
        {
          "$elemMatch": {
            "outerId": 3,
            "innerArr": innerArr
          }
        }
      ]
    }
  },
  {
    "$set": {
      "outerArr.$[i].innerArr.$[j].type": "Reserved"
    }
  },
  {
    "arrayFilters": [
      { "i.outerId": { "$in": [1, 2, 3] } },
      { "j.date": "2023-08-3" }
    ]
  }
)

Hi Vishal,

Thanks for suggestion.

Is it possible to give the solution you have provided in spring mongodb syntax ? Atleast the query format ?

Hello @Manjunath_k_s,

I don’t know more about spring syntax, so I would suggest you ask a new topic with the java and spring-data-odm tags so the related person will help you.