-
Type: Improvement
-
Resolution: Unresolved
-
Priority: Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Write Ops
-
None
-
Query Optimization
The current structure of an update command is this:
{ update: <collection>, updates: [ { q: <query>, u: <document or pipeline>, replacement: <boolean> upsert: <boolean>, multi: <boolean>, collation: <document>, arrayFilters: <array>, hint: <document|string> }, ... ],
The u field has three different semantics:
- it can be an aggregation pipeline
- it can be an update specification, meaning that all top-level fields are "$"-prefixed and represent update operators
- it can be a replacement document, meaning that the document matching the query is replaced in total by this document.
On the client side, these three semantics are represented by three different methods/functions, so the client always knows the difference between them. However, the server can only tell the difference between the second and third by examining the keys of the document to check for a "$" prefix. This has a (probably small) performance cost.
One unfortunate consequence of this API is that we were not able to fully relax the restriction on "$"-prefixed fields for update (and findAndModify), because doing so would introduce an ambiguity in the API. So applications are forced to use more complicated update pipelines if they need "$"-prefixed fields.
We can improve this situation by enhancing the command protocol to allow drivers to indicate to the server whether the update document is intended as a replacement or an update specification. This could be in the form of a new boolean field for each update document, or a new "replace" command (a similar proposal would be needed for findAndModify). Obviously it would have to be optional in order to support old clients, so the server would have logic like this:
boolean isReplacement = command specified replacement: true || command did not specify replacement and there are no $-prefixed fields
Similarly, drivers would add this new field gated by a wire version check, and could also remove its current checks for "$"-prefixed fields for all updates. This would be a bit tricky, as that logic in most drivers is likely buried in a place where wire version is not accessible, but possible.