如何使用psycopg2将JSON批量加载到Postgres?

时间:2018-01-29 23:38:37

标签: python psycopg2

我一直在从这样的文件中加载json数据:

with open("data.json") as jd:
    print("loading json")
    j = json.load(jd)
    print("inserting")
    SendToPostGres(j)

def SendToPostGres(incs):
    length = len(incs)
    processed = 0
    pgParams = {
            'database': 'mydb',
            'user': 'hi',
            'password': '2u',
            'host': 'somedb.com',
            'port': 1111
            }
    conn = psycopg2.connect(**pgParams)
    curs = conn.cursor()

    for i in incs:
        curs.execute("insert into MY_TABLE (data) values (%s)", [Json(i)])
        processed += 1
        conn.commit()
        print("%s processed, %s remaining" % (processed, length+1-processed))

这非常低效。我已经尝试使用谷歌搜索并查看其他帖子,但我似乎无法获得所需的效果:"对于我的json列表中的每个项目,在我的数据库中创建一行在postgres中存储为json类型的相应数据。"

有人可以向我解释最有效的批量做法吗?

更新

根据下面的答案,我已尝试更新以使用extras中的execute_values函数。我现在收到的错误是:

"字符串索引超出范围"

请注意,我尝试更改页面大小,因为我认为这可能是相关的。我尝试过的并没有奏效。但它可能仍然是一个问题。

def SendToPostGres(incs):
    values = []
    for i in incs:
        values.append(json.dumps(i))

    pgParams = {
            'database': 'MY_DB',
            'user': 'hi',
            'password': '2u',
            'host': 'somedb.com',
            'port': 5432
            }
    conn = psycopg2.connect(**pgParams)
    curs = conn.cursor()

    try:
        psycopg2.extras.execute_values(curs, "insert into incidents (data) values (%s)", values, page_size=len(values))
    except Exception as e:
        raise e
    rows = curs.fetchall()
    curs.close()

1 个答案:

答案 0 :(得分:1)

使用psycopg2中的extras.execute_values。

使用'%s'查询中的语法,用于指定应注入值的位置。

与目前的方法相比,这是非常快的。

from psycopg2 import extras

def queryPostgresBulk(conn, query, values):

    _query = query
    _values = values
    _conn = conn
    _cur = _conn.cursor()
    try:
        extras.execute_values(_cur, _query, _values, page_size=_values.__len__())
    except Exception, e:
        raise e
    rows = _cur.fetchall()
    _cur.close()

    return rows

更新为OP评论:

使用json.dumps()将你的dicts列表转换为json字符串的字符串元组列表,这是函数所期望的格式。将它传递给json字符串的 json字符串元组列表,而不是代表json对象的字符串。

import json

_values = []
for dict in list
    _values.append((json.dumps(dict),))

或者列表理解:

_values = [(json.dumps(x),) for x in list]

另外值得指出的是,您所加载的数据不是有效的json格式,而且没有顶级的单个密钥。

再次更新为OP评论:

您需要提供元组列表作为值,json字符串在该元组内。如果要注入值的唯一数据是json字符串,则需要将for循环构建值更新为:

for i in incs:
    values.append((json.dumps(i),))

我不确定为什么我会发布这个帖子,因为你对我的两个早期版本的问题进行了正确的回答...希望它能帮助其他人。