我如何使用 python 防止 rethinkdb 上的重复记录

How do i prevent duplicate records on rethinkdb using python

如果没有以前的记录,我只想将记录插入 table,例如我有一个 table 用户,我只想添加具有 phone 的唯一用户数字

{"name":"john smith", "Age":30 , "phone_number": "556"}

如果要添加另一个具有相同 phone 号码的用户,我不希望能够添加他们。现在我正在尝试使用过滤器来确定我是否有包含 phonenumber

的现有记录
r.db(DB).table('users').filter(
    {'phone_number': new_practice['phone_number']},       
    default=r.error()).run(conn)

这就是我尝试使用该方法来查找用户是否存在的方式,但似乎并没有给我想要的东西

使用 RethinkDB 没有好的方法安全做到这一点。这已在 issue on github 中讨论过,并且与唯一二级索引以及保证原子性有关。本质上你必须做两个操作。先查找phone号码是否已经存在,如果没有再添加记录

RethinkDB does not support unique secondary indexes even for non-sharded tables. (Source: Using secondary indexes in RethinkDB)

所以我们有一个竞争条件。两个请求可以同时 运行 返回 phone 号码不存在,然后都插入新记录。以下 不安全 代码将执行此操作:

new_record = {"name": "john smith", "Age": 30, "phone_number": "556"}
filter_predicate = {"phone_number": new_record["phone_number"]}
test = r.table('users').filter(filter_predicate).count().eq(0)
r.branch(test, r.table('users').insert(new_record), None).run()

这里是 运行 的输出:

In [92]: for document in r.table('users').run(): print(document)

In [93]: new_record = {"name": "john smith", "Age": 30, "phone_number": "556"}

In [94]: filter_predicate = {"phone_number": new_record["phone_number"]}

In [95]: test = r.table('users').filter(filter_predicate).count().eq(0)

In [96]: r.branch(test, r.table('users').insert(new_record), None).run()
Out[96]: 
{u'deleted': 0,
 u'errors': 0,
 u'generated_keys': [u'2c0ffb27-cfdb-44e7-a416-4f7be5d97ea9'],
 u'inserted': 1,
 u'replaced': 0,
 u'skipped': 0,
 u'unchanged': 0}

In [97]: for document in r.table('users').run(): print document
{u'phone_number': u'556', u'Age': 30, u'id': u'2c0ffb27-cfdb-44e7-a416-4f7be5d97ea9', u'name': u'john smith'}

In [98]: r.branch(test, r.table('users').insert(new_record), None).run()

In [99]: for document in r.table('users').run(): print document
{u'phone_number': u'556', u'Age': 30, u'id': u'2c0ffb27-cfdb-44e7-a416-4f7be5d97ea9', u'name': u'john smith'}

想到的一种变通方法是尝试优雅地失败。也就是说,我们进行初始检查以查看文档是否存在,如果不存在,我们将添加它。然后我们必须检查重复项。如果发现重复项,则进行清理。我们需要某种决胜局,例如插入文档的时间(最早的是赢家)。任何希望我们的文档具有唯一 phone 编号的查询也需要考虑到这一点。如果两个文档具有相同的 phone 编号按时间升序排列,并且 select 第一个。