Python Eve:防止在不使用唯一字段的情况下插入重复项
我试图通过以下方法防止插入重复文档:Python Eve:防止在不使用唯一字段的情况下插入重复项,python,duplicates,eve,objectid,Python,Duplicates,Eve,Objectid,我试图通过以下方法防止插入重复文档: 从所需端点获取所有文档的列表,该列表将包含JSON格式的所有文档。此列表称为可用文档 在插入数据之前,使用pre\u POST_uu钩子处理请求。我没有使用insert钩子上的,因为我需要在验证之前这样做 因为我们可以访问request对象,所以使用request.json将有效负载格式化为json 检查request.json是否已包含在available\u文档中 如果新文档不是唯一的副本,则插入新文档,否则中止 使用这种方法,我得到了以下代码片段: d
可用文档
pre\u POST_uu
钩子处理请求。我没有使用insert钩子上的,因为我需要在验证之前这样做
request
对象,所以使用request.json
将有效负载格式化为jsonrequest.json
是否已包含在available\u文档中
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 = [{'foo': ObjectId('565e12c58b724d7884cd02bb'), 'bar': [ObjectId('565e12c58b724d7884cd02b9'), ObjectId('565e12c58b724d7884cd02ba')]}]
{'foo': '565e12c58b724d7884cd02bb', 'bar': ['565e12c58b724d7884cd02b9', '565e12c58b724d7884cd02ba']}
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()
有效负载request.json
如下所示:
available_docs = [{'foo': ObjectId('565e12c58b724d7884cd02bb'), 'bar': [ObjectId('565e12c58b724d7884cd02b9'), ObjectId('565e12c58b724d7884cd02ba')]}]
{'foo': '565e12c58b724d7884cd02bb', 'bar': ['565e12c58b724d7884cd02b9', '565e12c58b724d7884cd02ba']}
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()
如您所见,传递给API的文档和已经存储在DB中的文档之间的唯一区别是ID的数据类型。由于这个事实,我上面代码片段中的if
-语句的计算结果为True
,并判断要插入的文档不是重复的,而它肯定是重复的
是否有方法检查传递的文档是否已在数据库中?我不能使用唯一字段,因为所有文档字段的组合只需要唯一。有一个唯一标识符(我在本例中省略了它),但这不适合进行所需的比较,因为它是一种时间戳
我认为像在键
foo
和bar
上按ObjectIDs
的方式转换给定的ID会起到作用,但我不知道如何实现这一点,因为我不知道从何处获取数据类型ObjectID
。您的方法将比为字段设置唯一规则慢得多
因为从您的示例中,您要比较objectid,所以您不能简单地将它们用作集合的\u id
字段吗?在Mongo(当然还有Eve)中,默认情况下该字段是唯一的。事实上,你甚至没有定义它。您根本不需要做任何事情,因为使用现有id发布文档会立即失败
如果你不能这样做(也许你需要比较一个不同的objectid字段,但出于某种原因,你不能简单地为字段设置一个唯一的规则),我会考虑在db中查询字段值,而不是从db中获取所有文档,然后在代码中顺序扫描它们。类似于db.find({db\u field:new\u document\u field\u value})
。如果返回true,则新文档是重复的。确保对db_字段
进行了索引(这通常也适用于标记有唯一
规则的字段)
在评论后编辑。一个微不足道的实现可能是这样的:
available_docs = [{'foo': ObjectId('565e12c58b724d7884cd02bb'), 'bar': [ObjectId('565e12c58b724d7884cd02b9'), ObjectId('565e12c58b724d7884cd02ba')]}]
{'foo': '565e12c58b724d7884cd02bb', 'bar': ['565e12c58b724d7884cd02b9', '565e12c58b724d7884cd02ba']}
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()
def pre_POST_回调(资源、请求):
#使用eve连接检索mongodb集合
docs=app.data.driver.db['docs']
如果docs.find_one({'foo':}):
flask.abort(422,description='Document是重复的,并且已经在数据库中了')
app=Eve()
app.run()
以下是我防止重复记录的方法:
def on_insert_订阅(项目):
c_subscription=app.data.driver.db['subscription']
用户=解码令牌()
如果用户:
对于项目中的项目:
如果c_subscription.find_one({
“主题”:ObjectId(项['topic']),
“客户端”:ObjectId(用户['user\u id'])
}):
中止(422,description=“客户端已订阅此主题”)
其他:
项['client']=ObjectId(用户['user\u id'])
其他:
中止(401,description='请提供正确的凭据')
我在这里做的是为客户端创建订阅。如果一个客户已经订阅了一个主题,我抛出422。
注意:客户端ID是从JWT令牌解码的。即使它是相同的数据类型,代码仍然会失败,因为它们是不同的对象。如果你想把它们看作是相似的,你就必须创建一个比较函数,而不是使用<代码> >如果不是请求。JSON在可用的Sims中,我得到了关于不同对象(比如引用)的观点。但是类似于a={'albert':2015}l=[]l.append(a)b={'albert':2015}print(b in l)
的计算结果为True
。所以我想到了这个方法。但是你处理的是对象而不是数字,请看下面的例子,它能更好地反映你的情况:这是真的。由于objectid是唯一的,所以我认为将它们相互比较(如字符串)将有助于作业。我仍然认为这个想法会奏效,但我的方法有点错误。因此我会使用eve的方法进行db.find({db\u field:new\u document\u field\u value})
查询,其中={db\u field:new\u document\u field\u value}
方法,我不会吗?或者有没有一种方法可以在内部执行此操作,因为我打算用pre_POST钩子检查重复的内容?我可以使用eve的底层pymongo实例吗?如何确保索引处于活动状态?