首页 > 解决方案 > Django:有没有办法有效地批量 get_or_create()

问题描述

我需要导入论文和作者的数据库(以 JSON 格式给出)。数据库非常大(1.94 亿个条目),所以我不得不使用 django 的 bulk_create() 方法。

第一次加载作者时,我使用以下脚本:

def load_authors(paper_json_entries: List[Dict[str, any]]):
    authors: List[Author] = []
    for paper_json in paper_json_entries:
        for author_json in paper_json['authors']:
            # len != 0 is needed as a few authors dont have a id
            if len(author_json['ids']) and not Author.objects.filter(author_id=author_json['ids'][0]).exists():
                authors.append(Author(author_id=author_json['ids'][0], name=author_json['name']))
    Author.objects.bulk_create(set(authors))

但是,这太慢了。瓶颈是这个查询:

and not Author.objects.filter(author_id=author_json['ids'][0]).exists():

不幸的是,我必须进行这个查询,因为当然一个作者可以写多篇论文,否则会出现密钥冲突。

有没有办法get_or_create()使用 bulk_create 有效地实现类似正常的东西?

标签: jsondjangodatabasebulkinsertbulk-load

解决方案


为避免使用现有唯一键创建条目,您可以启用该ignore_conflicts参数:

def load_authors(paper_json_entries: List[Dict[str, any]]):
    Author.objects.bulk_create(
        (
            Author(author_id=author_json['ids'][0], name=author_json['name'])
            for paper_json in paper_json_entries
            for author_json in paper_json['authors']
        ),
        ignore_conflicts=True
    )

推荐阅读