【问题标题】:How to do a bulk insert or increment type operation with the Django ORM如何使用 Django ORM 进行批量插入或增量类型操作
【发布时间】:2014-11-23 02:37:27
【问题描述】:

我有一个在这里定义的模型:

class VectorSet(models.Model):
    word = models.CharField(max_length=255)
    weight = models.IntegerField()
    session = models.ForeignKey(ResearchSession)

我想编写一个函数,该函数将获取一个单词列表和一个 ResearchSession,对于该单词列表中的每个单词,如果它尚不存在,则创建一个权重为 1 的新行,否则采用行并将权重增加 1。

到目前为止,我已经得到了这个:

def train(words, session):
    for i in words:
        result, created = VectorSet.objects.get_or_create(word=i, session=session,
                                                          defaults={'weight' : 1})
        if not created:
            result.weight = F('weight') + 1
            result.save()

我相当有信心有一种方法可以通过一个查询来做到这一点,但是我不能完全弄清楚这可能是什么,或者是否可以通过原始 SQL 使用 django 代码。

【问题讨论】:

标签: python django postgresql


【解决方案1】:

我认为除了bulk_create 之外,目前没有开箱即用的批量插入解决方案。根据您的数据库,另一种解决方案是使用atomic 在事务中执行get_or_create。例如:

from django.db import transaction

@transaction.atomic
def train(words, session):
    for i in words:
        result, created = VectorSet.objects.get_or_create(word=i, session=session,
                                                      defaults={'weight' : 1})
        if not created:
            result.weight = F('weight') + 1
            result.save()

否则,您也许可以使用 DB API executemany

cursor.executemany('INSERT INTO vectorset (field1, field2, field3) VALUES (?, ?, ?)', data)

【讨论】:

    【解决方案2】:

    逻辑很简单,但是我们需要多次命中DB,也就是多次查询:

    qs = VectorSet.objects.filter(word__in=words, session=session)
    qs.update(weiget=models.F('weight')+1)
    VectorSet.objects.bulk_insert(VectorSet(session=session, word=w, weight=1)
      for w in words if w not in qs.value_list('word', flat=True))
    

    Django 1.7 中也有一个update_or_create,但目前它不区分更新的默认值和创建的默认值:

    for w in words:
        VectorSet.objects.update_or_create(word=w, session=session,
                                        defaults={'weight': models.F('weight')+1})
    

    因此,上面的代码将无法通过int(models.F('weight')+1) 创建(我们可以覆盖__int__ 方法,但太hack 没有意义...IMO)

    【讨论】:

      猜你喜欢
      • 2011-05-16
      • 1970-01-01
      • 1970-01-01
      • 2012-09-24
      • 2011-04-09
      • 2019-10-24
      • 2018-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多