2014-11-23 32 views
0

我有一个模型批量插入或增量式操作如下定义:如何做Django的ORM

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() 

我相当确信有一种方法可以用一个查询来实现,但我无法弄清楚可能是什么,或者是否可以用django代码处理原始SQL。

+0

至少相关:http://stackoverflow.com/问题/ 2252530/efficent-way-to-bulk-insert-with-get-or-create-in-django-sql-python-django – alecxe 2014-11-23 02:41:39

+0

对我来说看起来非常好。 – dursk 2014-11-23 04:56:38

回答

0

我认为目前还没有开箱即用的解决方案来做批量插入,而不是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) 
0

逻辑很简单,但是我们需要打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__的方法,但也劈死意义...... IMO)

相关问题