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

我试图通过以下方法防止插入重复文档:

  • 从所需端点获取所有文档的列表,该列表将包含JSON格式的所有文档。此列表称为
    可用文档
  • 在插入数据之前,使用
    pre\u POST_uu
    钩子处理请求。我没有使用insert钩子上的
    ,因为我需要在验证之前这样做
  • 因为我们可以访问
    request
    对象,所以使用
    request.json
    将有效负载格式化为json
  • 检查
    request.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实例吗?如何确保索引处于活动状态?