Adding mongoDB document-array-element using Python Eve -


background: (using eve , mongo)

i'm working in python using eve rest provider library connecting , mongodb expose number of rest endpoints database. i've had luck using eve far, i've run problem might bit beyond eve can natively.

my problem mongodb document format has field (called "slots"), value list/array of dictionaries/embedded-documents.

so mongodb document structure is:

{    blah1: data1,    blah2: data2,    ...    slots: [        {thing1:data1, thing2:data2},        {thingx:datax, thingy:datay}    ] } 

i need add new records (i.e. add pre-populated dictionaries) 'slots' list.

if imagine doing insert directly via pymongo like:

mongo.connection = mongoclient() mongo.db = mongo.connection['mydb'] mongo.coll = mongo.db['mycollection']  ...  mongo.coll.update({'_id' : document_id},                    {'$push': { "slot" : {"thing1":"data1","thingx":"datax"}  }  } ) 

the rest action/uri combo action post '_id/slots', e.g. uri of /app/012345678901234567890123/slots.

problem: (inserting element array in eve)

from so: how add list type in python eve without replacing old values , eve project issue appears eve doesn't support operating on mongodb embedded documents (or arrays?) unless entire embedded document rewritten, , rewriting whole array undesirable in case.


so, assuming true eve doesn't have method allow inserting of array elements (and given have numerous other endpoints working inside of eve)...


... i'm looking way, inside of eve/flask configuration multiple working endpoints, intercept , change eve's mongodb write 1 endpoint.

i know (worst case) can override routing of eve , write hand, have manage _updated , hand check & change documents _etag value, both things prefer not have write new code for.

i've looked @ eve's datebase event hooks don't see way modify database commands executed (i can see how change data, not commands).

anyone else solved problem already? if not ideas on direct path implement hand? (hopefully reusing of eve possible because want continue using eve (already working) endpoints)

this interesting question. believe in order achieve goal need perform 2 actions:

  1. build , pass custom validator.
  2. build , pass custom mongo data layer.

this might sound work, that's not case.


custom validator

a custom validator going needed because when perform patch request on "push-enabled" endpoint want pass document syntactically different endpoint validation schema. going pass dict ({"slot": {"thing1": "data1", "thingx": "datax"}}) whereas endpoint expects list:

'mycollection': {     'type': 'list',     'schema': {         'type': 'dict',         'schema': {             'thing1': {'type': 'string'},             'thingx': {'type': 'string'},         }     } } 

if don't customize validation end validation error (list type expected). guess custom validator like:

from eve.data.mongo.validation import validator flask import request  class myvalidator(validator):     def validate_replace(self, document, _id, original_document=none):         if self.resource = 'mycollection' , request.method = 'patch':             # want perform real validation here             return true         return super(validator, self).validate(document) 

mind did not try code might need adjustment here , there.

an alternative approach set alternative endpoint patch requests. endpoint consume same datasource , have dict-like schema. avoid need custom validator , also, still have normal atomic field updates ($set) on standard endpoint. think approach better, don't lose functionality , reduce complexity. guidance on multiple endpoints hitting same datasource see the docs


custom data layer

this needed because want perform $push instead of $set when mycollection involved in patch request. maybe:

from eve.io.mongo import mongo flask import request  class mymongo(mongo):     def update(self, resource, id_, updates, original):         op = '$push' if resource == 'mycollection' else '$set'         return self._change_request(resource, id_, {op: updates}, original) 

putting together

you use custom validator , data layers upon app initialisation:

app = eve(validator=myvalidator, data=mymongo) app.run() 

again did not test of this; it's sunday , i'm on beach might need work should work.

with being said, going experiment adding support push updates standard mongo data layer. new pair of global/endpoint settings, mongo_update_operator/mongo_update_operator implemented on private branch. former defaults $set api endpoints still perform atomic field updates. 1 decide endpoint should perform else, $push. implementing validation in clean , elegant way little tricky but, assuming find time work on it, not unlikely make eve 0.6 or beyond.

hope helps.


Comments

Popular posts from this blog

Java 3D LWJGL collision -

spring - SubProtocolWebSocketHandler - No handlers -

methods - python can't use function in submodule -