I don't know why these two results are different

Hi, I currently working with java and mongodb.

original documents :

{
  _id: 'test1',
  arr: [ '111', '222', '333', '333' ]
},
{
  _id: 'test2',
  arr: [ '111', '222', '333' ]
}

executed java code No.1 :

Bson filter = Filters.and(Filters.exists("arr"), Filters.all("arr", "333"));
Bson bson = Updates.set("arr.$", "999");
UpdateResult result = collection.updateMany(filter, bson);

executed java code No.2 :

Bson filter = Filters.all("arr", "333");
Bson bson = Updates.set("arr.$", "999");
UpdateResult result = collection.updateMany(filter, bson);

Result of No.1 :

{
  _id: 'test1',
  arr: [ '999', '222', '333', '333' ]
},
{
  _id: 'test2',
  arr: [ '999', '222', '333' ]
}

Result of No.2 :

{
  _id: 'test1',
  arr: [ '111', '222', '999', '333' ]
},
{
  _id: 'test2',
  arr: [ '111', '222', '999' ]
}

What I intended was No.2, and by deleting “and” and “exists”, it worked the way I wanted.
but at the same time, new questions arose.

Isn’t a filter that checks if a field exists a “redundant” condition?
so I thought the result would be the same even if I deleted it.

I don’t know why these two filters give different results…

Hi @gantodagee_N_A and welcome to the MongoDB community.

As mentioned in the MongoDB documentation for $(update) operator, for multiple array matches, the $ operator might behave ambiguously.

Since for the query 1, both the conditions inside the AND operator are true, I think the $ becomes unreliable and points to the first element for both the documents match.

However, in the query 2, the $ can point to the exact element according to the filter criteria and set the 999 value at the required position.

If for your case, the second query performs the exact operation as expected, the recommendation would be use the same in order to avoid confusions in the future.

I tried to replicate the above in my local environment and below are the results for the following:
Query1:

Atlas atlas-b8d6l3-shard-0 [primary] test> db.AllAnd.updateMany( { arr: { $exists: true, $all: [ 333]}}, { $set: { "arr.$": 999} })
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 2,
  modifiedCount: 2,
  upsertedCount: 0
}
Atlas atlas-b8d6l3-shard-0 [primary] test> db.AllAnd.find()
[
  { _id: 'test1', arr: [ 999, 222, 333, 333 ] },
  { _id: 'test2', arr: [ 999, 222, 333 ] }
]

Query 2:

Atlas atlas-b8d6l3-shard-0 [primary] test> db.AllAnd.updateMany( { "arr": 333}, { $set: { "arr.$":  999}})
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 2,
  modifiedCount: 2,
  upsertedCount: 0
}
Atlas atlas-b8d6l3-shard-0 [primary] test> db.AllAnd.find()
[
  { _id: 'test1', arr: [ 111, 222, 999, 333 ] },
  { _id: 'test2', arr: [ 111, 222, 999 ] }
]

We tried to perform the query 2 in the Java sync driver version 4.9, and to get the desired output as mentioned, we modified the query as:

Bson filter = Filters.eq("arr", 333);
Bson update = Updates.set("arr.$", 999);
UpdateResult result = collection.updateMany(filter, update);


{"_id": "test1", "arr": [111, 222, 333, 333]}
{"_id": "test2", "arr": [111, 222, 333]}
Matched documents: 2
Modified documents: 2
{"_id": "test1", "arr": [111, 222, 999, 333]}
{"_id": "test2", "arr": [111, 222, 999]}

Let us know if you have any further queries.

Best Regards
Aasawari

3 Likes

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