【问题标题】:Correct way to add entry to a database only if entry does not exist; using python + peewee仅当条目不存在时才将条目添加到数据库的正确方法;使用 python + peewee
【发布时间】:2019-08-06 13:14:00
【问题描述】:

我最近遇到了以下模式:

我在 mysql 中有一个表,其中定义了一个(可能是复合的)主键。表中已有一些条目。

我正在运行一些将新条目推送到表中的更新脚本。这些脚本被设计为重复运行,它们可能会尝试推送重复的条目。

我经常会遇到这样一种情况:我有一个数据框,我只想推送 mysql 表中的新行。

例如 peewee 模型:

class MyTable(pwe.Model):
  colA = pwe.IntegerField(primary_key=True)
  colB = pwe.IntegerField()

示例数据框:

>>> df = pd.DataFrame([[1,2],[2,3],[3,4]], columns=['colA','colB'])
>>> df
   colA  colB
0     1     2
1     2     3
2     3     4

尝试的解决方案

我尝试了许多解决方案,但没有一个是理想的:

  1. 使用MyTable.get_or_create。不建议用于大量数据。
  2. 使用MyTable.insert_many()MyTable.batch_create() 并手动检查数据库中已有哪些条目:
    with MyTable._meta.database.atomic():
        existing_keys = [r.colA for r in MyTable.select(MyTable.colA)]
        df = df[~df['colA'].isin(existing_keys)]
        MyTable.batch_create([MyTable(**rec) for rec in df.to_dict('records')])

我对此有多个问题。

  • 简直丑陋。
  • 有点长。
  • 我不想每次更新时都拉下整个colA
  • 我不确定这是否能解决并发问题 - 如果其他人在我的计算 existing_keys 和调用 batch_create 之间推送数据怎么办?

问题

当数据库中可能已经存在一些行时,推荐将大量数据推送到表的方法是什么?

【问题讨论】:

    标签: python mysql database peewee


    【解决方案1】:

    取决于您的数据库,但大多数支持某种 INSERT OR IGNORE / INSERT ... ON CONFLICT IGNORE。因此,您可以进行批量插入并依靠主键或其他一些唯一约束来触发“OR IGNORE”逻辑。

    http://docs.peewee-orm.com/en/latest/peewee/api.html#Insert.on_conflict

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多