大导入到django postgres数据库

时间:2015-08-08 00:24:01

标签: python django database postgresql

我有一个包含4,500,000行的CSV文件,需要导入到我的django postgres数据库中。此文件包含关系,因此不像使用COPY将CSV文件直接导入数据库那么容易。

如果我想直接加载到postgres,我可以更改CSV文件以匹配数据库表,但我不知道如何获得关系,因为我需要知道插入的id以建立关系。

有没有办法生成可以获取最后一个id并在将来的语句中使用它的sql插件?

我最初使用django ORM编写了这个,但它会采取长期的方式来做到这一点,它似乎正在放慢速度。我删除了所有索引和约束,所以这不应该是问题。

数据库在我的计算机上本地运行。我想,一旦我将数据存入数据库,就很难将其转储并重新加载到生产数据库中。

那么如何才能将这些数据以正确的关系存入我的数据库呢?

请注意,我不了解JAVA,所以这里建议的答案对我来说不是很实用:Django with huge mysql database

编辑: 以下是更多细节:

我的模型是这样的:

class Person(models.Model):
    name = models.CharField(max_length=100)
    offices = models.ManyToManyField(Office)
    job = models.ForeignKey(Job)

class Office(models.Model):
    address = models.CharField(max_length=100)

class Job(models.Model):
    title = models.CharField(max_length=100)

所以我有一个人可以有一份工作,但有很多办公室。 (我的真实模型有更多的领域,但你明白了)。

我的CSV文件是这样的:

name,office_1,office_2,job
hailey,"123 test st","222 USA ave.",Programmer

还有更多的领域,但我只包括相关的领域。

所以我需要创建person对象和office对象并将它们联系起来。工作对象已经创建,所以我需要做的就是找到工作并将其保存为工作人员。

此前原始数据不在数据库中。只有平面文件。我们试图使它成为关系,因此有更多的灵活性。

谢谢!

1 个答案:

答案 0 :(得分:1)

嗯,这是一个。

当您说关系时,它们都在一个CSV文件中?我的意思是,像这样,假设一个简单的数据模型,与自身有关系吗?

id;parent_id;name
4;1;Frank
1;;George
2;1;Costanza
3;1;Stella

如果是这种情况并且它不正常,我会写一个Python脚本来重新排序这些,然后导入它们。

我有一个场景,我有一些CSV文件,但它们来自个别模型,我加载了第一个父模型,然后是第二个,等等。

我们在这里写了自定义导入器,它将从单个CSV中读取数据,并对其进行一些处理,例如检查它是否已存在,是否有效等等。每个CSV文件的方法。

对于足够大的CSV,我们只需将它们分成较小的文件(每个约200k条记录),然后依次处理它们。区别在于这个大CSV所依赖的所有先前数据已经在数据库中,通过前面描述的相同方法导入。

没有例子,我不能发表更多评论。

修改

好吧,既然你给了我们你的模型,并且基于工作模型已经存在的事实,我会选择这样的事情:

  1. 创建一个自定义方法,即使您可以从shell调用它。方法/函数或其他任何方法,它将接收文件的单行。
  2. 在该方法中,了解该人与之相关的办公室数量。搜索以查看该数据库中是否已存在该办公室。如果是这样,用它来联系一个人和办公室。如果没有,请创建并关联它们
  3. 找工作。它存在吗?是的,然后使用它。没有?创建它然后再使用它。
  4. 这样的事情:

    def process_line(line):
    
        data = line.split(";")
        person = Person()
        # fill in the person details that are in the CSV
        person.name = data[1]
        person.name = data[2]
        person.save() # you'll need to save to use the m2m
    
        offices = get_offices_from_line(line) # returns the plain data, not office instances
    
        for office in offices:
    
            obj, create = get_or_create(office_address=office)
            if (obj):
                person.offices.add(obj)
    
            if (create):
                person.offices.add(create)
    
        job_obj, job_create = get_or_create(job_title=data[5])
        # repeat
    

    请注意,上述功能未经过测试或防范任何类型的错误。你需要:

    1. 自己动手;
    2. 创建标识每个人所拥有的办公室的功能。我不知道这些数据,但也许如果你看看第一个办公室前面的字段,直到所有办公室之后的第一个字段,你就可以掌握所有这些;
    3. 您需要创建一个函数来解析高级文件,迭代这些行并沿着闪亮的导入函数传递它们。
    4. 以下是get_or_create的文档:https://docs.djangoproject.com/en/1.8/ref/models/querysets/#get-or-create