Mik*_*utz 6 python rest mongodb eve
背景:(使用Eve和Mongo)
我正在使用Eve REST提供程序库连接和使用mongoDB 从Python中工作,以从数据库中公开许多REST端点.到目前为止,我使用Eve已经好运了,但是我遇到的问题可能超出了Eve本身可以做的事情.
我的问题是我的mongoDb文档格式有一个字段(称为"插槽"),其值是字典/嵌入文档的列表/数组.
所以mongoDB文档结构是:
{
blah1: data1,
blah2: data2,
...
slots: [
{thing1:data1, thing2:data2},
{thingX:dataX, thingY:dataY}
]
}
Run Code Online (Sandbox Code Playgroud)
我需要在'slots'列表中添加新记录(IE添加预先填充的词典).
如果我想通过pymongo直接进行插入,它看起来像:
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"} } } )
Run Code Online (Sandbox Code Playgroud)
我想要执行此操作的REST动作/ URI组合是POST'_id/slots',例如URI /app/012345678901234567890123/slots.
问题:(在Eve中将元素插入数组中)
从SO:如何在Python Eve中添加列表类型而不替换旧值和eve项目问题看起来Eve目前不支持在mongoDB嵌入式文档(或数组?)上运行,除非整个嵌入式文档被重写,并重写在我的情况下,整个数组非常不受欢迎.
所以,假设它真正的Eve没有一个允许插入数组元素的方法(并且鉴于我已经有许多其他端点在Eve内部运行良好)...
...我现在正在寻找一种方法,在具有多个工作端点的Eve/Flask配置中,拦截并更改Eve的mongoDB写入仅针对这一个端点.
我知道(最坏的情况)我可以覆盖Eve的路由并完全手工编写,但后来我会管理_updated和手工检查并更改文档_etag值,这两件事我宁愿不必写新代码.
我看过Eve的Datebase事件挂钩,但是我没有看到修改执行的数据库命令的方法(我可以看到如何更改数据,但不能看到命令).
其他人已经解决了这个问题吗?如果没有关于最直接的手动实施的想法?(希望尽可能多地重复使用Eve,因为我确实希望继续使用Eve来处理所有(已经在工作的)端点)
这是个有趣的问题.我相信,为了实现您的目标,您需要执行两项操作:
这可能听起来像是太多的工作,但情况可能并非如此.
将需要自定义验证程序,因为当您在"启用推送"的端点上执行PATCH请求时,您希望传递一个语法,该语句在语法上与端点验证模式不同.您将传递一个dict({"slot": {"thing1": "data1", "thingX": "dataX"}}),而端点需要一个列表:
'mycollection': {
'type': 'list',
'schema': {
'type': 'dict',
'schema': {
'thing1': {'type': 'string'},
'thingX': {'type': 'string'},
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您不自定义验证,则最终会出现验证错误(list type expected).我想你的自定义验证器可能看起来像:
from eve.data.mongo.validation import Validator
from flask import request
class MyValidator(Validator):
def validate_replace(self, document, _id, original_document=None):
if self.resource = 'mycollection' and request.method = 'PATCH':
# you want to perform some real validation here
return True
return super(Validator, self).validate(document)
Run Code Online (Sandbox Code Playgroud)
请注意,我没有尝试此代码,因此可能需要在此处进行一些调整.
另一种方法是为PATCH请求设置备用端点.此端点将使用相同的数据源并具有类似dict的架构.这样可以避免使用自定义验证器,并且您仍然可以$set在标准端点上进行正常的原子字段更新().实际上我认为我更喜欢这种方法,因为你不会失去功能并降低复杂性.有关多个端点命中相同数据源的指导,请参阅文档
这是必需的,因为您要执行PATCH请求中涉及的$push而不是$setwhen mycollection.这样的事情可能是:
from eve.io.mongo import Mongo
from 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)
Run Code Online (Sandbox Code Playgroud)
然后,在应用初始化时使用自定义验证器和数据层:
app = Eve(validator=MyValidator, data=MyMongo)
app.run()
Run Code Online (Sandbox Code Playgroud)
我再次没有测试所有这些; 这是星期天,我在沙滩上,所以它可能需要一些工作,但它应该工作.
说了这么多,我实际上将尝试添加对标准Mongo数据层的推送更新的支持.一对新的全局/端点设置(如MONGO_UPDATE_OPERATOR/)mongo_update_operator在专用分支上实现.前者默认为$set所有API端点仍然执行原子字段更新.人们可以决定某个端点应该执行其他操作,例如a $push.以干净和优雅的方式实现验证有点棘手但是,假设我找到了工作时间,那么这不可能达到Eve 0.6或更高.
希望这可以帮助.