我试图通过以下方法阻止插入重复文档:
available_docs
。pre_POST_<endpoint>
挂钩以便在插入数据之前处理请求。我没有使用on_insert
挂钩,因为我需要在验证之前执行此操作。request
对象使用request.json
来获取有效负载JSON格式request.json
available_docs
使用这种方法,我得到了以下片段:
def check_duplicate(request):
if not request.json in available_sims:
print('Not a duplicate')
else:
print('Duplicate')
flask.abort(422, description='Document is a duplicate and already in database.')
available_docs
列表如下所示:
available_docs = [{'foo': ObjectId('565e12c58b724d7884cd02bb'), 'bar': [ObjectId('565e12c58b724d7884cd02b9'), ObjectId('565e12c58b724d7884cd02ba')]}]
有效负载request.json
如下所示:
{'foo': '565e12c58b724d7884cd02bb', 'bar': ['565e12c58b724d7884cd02b9', '565e12c58b724d7884cd02ba']}
如您所见,传递给API的文档与已存储在DB中的文档之间的唯一区别是ID的数据类型。由于这个事实,我上面代码段中的if
- 语句评估为True
,并判断要插入的文档不是重复文件,而它肯定是重复文件。
有没有办法检查传递的文档是否已经存在于数据库中?我无法使用唯一字段,因为所有文档字段的组合只需要是唯一的。有一个唯一的标识符(我在本例中省略了),但这不适合所需的比较,因为它是一种时间戳。
我认为像键foo
和bar
那样将ObjectIDs
的给定ID转换成ObjectID
就行了,但我不知道如何处理这个问题,因为我不知道从哪里获取数据类型{{1}}。
答案 0 :(得分:1)
您的方法比为字段设置唯一规则要慢 。
因为从你的例子中,你要比较objectids,你不能简单地将它们用作集合的_id
字段吗?在Mongo(当然还有Eve)中,该字段默认是唯一的。实际上,您通常甚至不定义它。您根本不需要做任何事情,因为具有已存在ID的文档的POST会立即失败。
如果你不能这样做(也许你需要比较一个不同的objectid字段,但由于某种原因,你不能简单地为该字段设置unique
规则),我会看一下查询db以获取字段值,而不是从db获取所有文档,然后在代码中按顺序扫描它们。像db.find({db_field: new_document_field_value})
这样的东西。如果返回true,则新文档是重复的。确保将db_field
编入索引(对于标有unique
规则的字段,通常也适用)
评论后编辑。一个简单的实现很可能是这样的:
def pre_POST_callback(resource, request):
# retrieve mongodb collection using eve connection
docs = app.data.driver.db['docs']
if docs.find_one({'foo': <value>}):
flask.abort(422, description='Document is a duplicate and already in database.')
app = Eve()
app.run()
答案 1 :(得分:1)
这是我防止重复记录的方法:
def on_insert_subscription(items):
c_subscription = app.data.driver.db['subscription']
user = decode_token()
if user:
for item in items:
if c_subscription.find_one({
'topic': ObjectId(item['topic']),
'client': ObjectId(user['user_id'])
}):
abort(422, description="Client already subscribed to this topic")
else:
item['client'] = ObjectId(user['user_id'])
else:
abort(401, description='Please provide proper credentials')
我在这里做的是为客户创建订阅。如果客户已经订阅了我扔422的主题。 注意:客户端ID是从JWT令牌解码的。