[JAVA-2690] Write operation using positional operator return incorrect value Created: 05/Dec/17  Updated: 27/Oct/23  Resolved: 02/Jan/18

Status: Closed
Project: Java Driver
Component/s: Write Operations
Affects Version/s: 3.6.0
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Jose Antonio Sanchez Murillo Assignee: Ross Lawley
Resolution: Works as Designed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Ubuntu Linux 16.04, MongoDB 3.6.0-RC8, MongoDB Java Driver 3.6.0-RC1



 Description   

Hello, I'm using the new positional operator for arrays included in MongoDB 3.6 but I've come to a bug which I don't know how to overcome. I'm executing the following operation both in Mongo Shell and with the Java driver:

db.getCollection('cloudMonitoringResource').update({"_id" : "0"}, {$push: {"deviceMetrics.$[i].metricValues.$[j].values": {"date": ISODate("2017-11-25 13:08:21.659Z"), "value": 1}}},  {arrayFilters: [{"i.metric" : "load"},{"j.day":"2017-11-25"}]})

in which I get the following result:

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })

Which means there's a match (my document exists with that Id) but the document was not modified since there isn't any element in the arrays matching the arrayFilters, however if I execute the update

db.getCollection('cloudMonitoringResource').update({"_id" : "0"}, {$push: {"deviceMetrics.$[i].metricValues.$[j].values": {"date": ISODate("2017-11-25 13:08:21.659Z"), "value": 1}}},  {arrayFilters: [{"i.metric" : "availability"},{"j.day":"2017-12-03"}]})

I get the following result:

WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

Which means 1 match, 0 upsertions but 1 document modified.

Now running the same sequence on the Java driver, I get the same result:

WriteResult{n=1, updateOfExisting=true, upsertedId=null}

Debugging the code, I've seen this in BaseWriteOperation:

private int getCount(final BulkWriteResult bulkWriteResult) {
        int count = 0;
        if (getType() == UPDATE || getType() == REPLACE) {
            count = bulkWriteResult.getMatchedCount() + bulkWriteResult.getUpserts().size();
        } else if (getType() == DELETE) {
            count = bulkWriteResult.getDeletedCount();
        }
        return count;
    }

So for an update, the n just take into account the matched count (1 in both cases) and the upserts (0 in both cases) but it ignores modifications (0 in the first case, 1 in the second) as a result, there's no way to distinguish when such an operation actually modifies the document or not so there's no way to know if the update has been successful or if the document continues unmodified.



 Comments   
Comment by Jeffrey Yemin [ 02/Jan/18 ]

It looks like you're using the legacy API (e.g. DBCollection) rather than the newer CRUD API (e.g MongoCollection). The DBCollection's update method returns an instance of com.mongodb.WriteResult, which does not include a count of the documents actually modified. The MongoCollection's updateMany method, however, returns an instance of com.mongodb.client.result.UpdateResult, which includes a modifiedCount property. This is the property that you're looking for.

So to get access to this property please use the new CRUD API.

Apologies in advance for any inconvenience this causes, but we're no longer expending resources maintaining the legacy API, as the newer CRUD API has been available since the 3.0 driver release.

Generated at Thu Feb 08 08:57:50 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.