google-code-export / morphia

Automatically exported from code.google.com/p/morphia
1 stars 0 forks source link

UpdateOperations with isolated() do not honor DatastoreImpl update with createIfMissing behavior #406

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
morphia 0.99 / morphia logging 0.99 / morphia validation 0.99
mongo-java-driver-2.7.3 / mongodb-osx-x86_64-2.0.4

The expected upsert behavior using update(query, ops, createIfMissing=true) 
fails to work when isolated() is used in the UpdateOperations. Instead the 
query always updates existing record after creating an initial record. Removing 
isolated() allows this method to be used with the expected upsert behavior. 
Also, using findAndModify(query, ops, false, true) upserts correctly with 
isolated() left in the ops.

The main difference I can see involves a block in DatastoreImpl, where it is 
calling disableValidation on the query used in the update. The combination of 
isolated and update seems to result in the query matching all existing 
documents in the collection and updating that result set. I believe I verified 
this by adding a second document to the collection via the CLI, and running the 
morphia update method again: all documents in the collection ended up with the 
update calls set operations from my morphia code.

        @SuppressWarnings("rawtypes")
        private <T> UpdateResults<T> update(Query<T> query, UpdateOperations ops, boolean createIfMissing, boolean multi, WriteConcern wc) {
                DBObject u = ((UpdateOpsImpl) ops).getOps();
                if (((UpdateOpsImpl) ops).isIsolated()) {
                        Query<T> q = query.clone();
                        q.disableValidation().filter("$atomic", true);
                        return update(q, u, createIfMissing, multi, wc);                
                }
                return update(query, u, createIfMissing, multi, wc);            
        }

compared to this block:

        public <T> T findAndModify(Query<T> query, UpdateOperations<T> ops, boolean oldVersion, boolean createIfMissing) {
                QueryImpl<T> qi = (QueryImpl<T>) query;

                DBCollection dbColl = qi.getCollection();
                //TODO remove this after testing.
                if(dbColl == null)
                        dbColl = getCollection(qi.getEntityClass());

                if (log.isTraceEnabled())
                        log.info("Executing findAndModify(" + dbColl.getName() + ") with update ");

                DBObject res = dbColl.findAndModify(qi.getQueryObject(), 
                                                                                        qi.getFieldsObject(), 
                                                                                        qi.getSortObject(), 
                                                                                        false, 
                                                                                        ((UpdateOpsImpl<T>) ops).getOps(), !oldVersion, 
                                                                                        createIfMissing);

                if (res == null) 
                        return null;
                else
                        return (T) mapr.fromDBObject(qi.getEntityClass(), res, createCache());
        }

...which sends the UpdateOperations from UpdateOpsImpl settings up to the 
driver without changing the QueryImpl fields through disableValidation().

Note: I have not stress tested this to see if either method actually isolates 
the update operation or not.

Thanks,
Jaron Sampson

Original issue reported on code.google.com by jaronsampson on 30 Apr 2012 at 7:00

Attachments:

GoogleCodeExporter commented 9 years ago
Clarification: <snip>"Instead the query always updates existing record after 
creating an initial record. " </snip>

If the collection was empty the first time the update method is executed, it 
inserts one record. All subsequent calls update that record with the update 
operations specified).

Original comment by jaronsampson on 30 Apr 2012 at 7:03

GoogleCodeExporter commented 9 years ago
Can you post a test case on https://github.com/mongodb/morphia/issues/406.  I'd 
love to isolate and fix this but i'm not sure what exactly the problem is.  But 
given that no one else has said anything like this, I'm leaning toward closing 
this issue for now.

Original comment by justin....@10gen.com on 24 Feb 2015 at 1:23