The findAndModify command will be re-implemented in terms of getExecutorDelete() and getExecutorUpdate(). If the findAndModify specifies remove, then it will use getExecutorDelete() to retrieve a PlanExecutor wrapping a DeleteStage. If findAndModify specifies update, then it will use getExecutorUpdate() to retrieve a PlanExecutor wrapping an UpdateStage.
In order to support findAndModify, the UpdateStage and the DeleteStage will be extended as follows:
- A returnDeleted option will be added to DeleteRequest, with a default of false. Find and modify operations will set this option to true. A delete PlanExecutor with returnDeleted set will return PlanExecutor::ADVANCED and an owned copy of the deleted object every time that it commits a document delete.
- The option returnDocs will be added to UpdateRequest, replacing the existing storeResultDoc option. It will take one of three values: RETURN_NEW, RETURN_OLD, or RETURN_NONE.
- If RETURN_NEW, the PlanExecutor will return PlanExecutor::ADVANCED with a owned or unowned copy of each updated document's post-image. If the update results in an insert, it will return ADVANCED once and return the inserted document.
- If RETURN_OLD, the PlanExecutor will return PlanExecutor::ADVANCED with an owned copy of each updated document's pre-image. If the update results in an insert, it will return neither ADVANCED nor will it return a copy of the updated document.
- If RETURN_NONE, the behavior will remain as is. Namely, the PlanExecutor will never return ADVANCED.
This change should allow for a sane implementation of CmdFindAndModify::explain(). The explain will return the UPDATE or DELETE plan tree being used to execute the operation.
- findAndModify will have the same behavior under concurrency as regular updates and deletes. It will take a MODE_IX lock and will use a YIELD_AUTO plan.
- If upsert is set to true, this will simply be passed through by setting the upsert flag on the UpdateRequest.
- findAndModify will continue to require its own handling for WriteConflictException retry and for collection creation on upsert into an empty collection.
- Find and modify will no longer depend on helpers such as deleteObjects() or mongo::update().
- This will probably involve a rewrite or at least clean up the parsing of the command BSON.