I am considering making a contribution to Python-eve, but am hoping to get a bit of feedback before putting in the work. I'd hate to put work in on this only to find that it is not wanted or that I am going about this the wrong way.
My colleagues have need of the ability to perform a mass update (i.e. update_many). I can add this functionality via a custom endpoint, but that seems clumsy when I can just add the functionality to the resource endpoints themselves. This would involve allowing operators in update documents (currently defaults to "$set" on all fields in eve/io/mongo.py) and allowing queries in updates. To do this, I would do the following:
- eve/flaskapp.py
- Add "PATCH" to `supported_resource_methods`.
- eve/endpoints.py
- Edit collections_endpoint to call `update` for `PATCH` requests.
- eve/io/mongo.py
- Modify `update()` to:
- If no operator is present in the first layer of the document, add the "$set" operator (this is currently done in all cases).
- If operators are present in the first layer of the document, just pass the document as is.
- eve/io/validation.py
- Add handling for operators to `Validate.validate_update()`.
I have mapped out how to add handling for operators to `Validate.validate_update()`, but am unsure if my approach is the best approach. Maybe I can make better use of cerberus for this, but I am not sure how to do so. To do this, I would attempt to make the best use of cerberus that I can.
There are several things that need to be done to prepare the document for validation through cerberus. There are a few different cases that need to be handled (including some that I am avoiding for now). To handle these, a new document would be constructed for validation as though the $set operation is being performed.
- Scalar operators
- $inc, $min, $max, $mul, $set, $setOnInsert:
- Remove the operator
- Move the field and value up a level
- Validate the field and value as if they are going to be used in a $set operation
- {"$min": {"field1": 1}} becomes {"field1": 1} for validation.
- $currentDate: Leave unhandled for now, until I have a better understanding of cerberus.Validator.
- Array Operators
- $addToSet, $push, $pull, $pullAll:
- Remove the operator
- Move the field and value up a level
- Turn any scalars into arrays
- Validate the field and value as if they are going to be used in a $set operation
- {"$push": {"field1": 1}} becomes {"field1": [1]}
- {"$pullAll": {"field1": [1, 2, 3, ...]}} becomes {"field1": [1, 2, 3, ...]}}
- $pop:
- Check that the value is either 1 or -1
- Remove from the document prior to validation
- Operators to skip for now, but which need to be handled later:
- Scalar Operators: $currentDate
- Array Operators: $, $[], $[<identifier>]
- Modifiers: $each, $position, $slice, $sort, $bit
I think this is the full set of required modifications and would be very happy to hear some feedback on this.