PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Criar/inserir Json no Postgres com solicitações e psycopg2


Parece que você deseja criar uma tabela com uma coluna chamada "data" . O tipo desta coluna é JSON. (Eu recomendaria criar uma coluna por campo, mas fica a seu critério.)

Neste caso, a variável data (que é lido a partir da solicitação) é uma list de dict s. Como mencionei no meu comentário, você pode fazer um loop sobre data e faça as inserções uma de cada vez como executemany() não é mais rápido do que várias chamadas para execute() .

O que eu fiz foi o seguinte:
  1. Crie uma lista de campos importantes para você.
  2. Percorrer os elementos de data
  3. Para cada item em data , extraia os campos em my_data
  4. Chame execute() e passe json.dumps(my_data) (Converte my_data de um dict em uma string JSON)

Tente isto:
#!/usr/bin/env python
import requests
import psycopg2
import json

conn = psycopg2.connect(database='NHL', user='postgres', password='postgres', host='localhost', port='5432')

req = requests.get('http://www.nhl.com/stats/rest/skaters?isAggregate=false&reportType=basic&isGame=false&reportName=skatersummary&sort=[{%22property%22:%22playerName%22,%22direction%22:%22ASC%22},{%22property%22:%22goals%22,%22direction%22:%22DESC%22},{%22property%22:%22assists%22,%22direction%22:%22DESC%22}]&cayenneExp=gameTypeId=2%20and%20seasonId%3E=20172018%20and%20seasonId%3C=20172018') 

# data here is a list of dicts
data = req.json()['data']

cur = conn.cursor()
# create a table with one column of type JSON
cur.execute("CREATE TABLE t_skaters (data json);")

fields = [
    'seasonId',
    'playerName',
    'playerFirstName',
    'playerLastName',
    'playerId',
    'playerHeight',
    'playerPositionCode',
    'playerShootsCatches',
    'playerBirthCity',
    'playerBirthCountry',
    'playerBirthStateProvince',
    'playerBirthDate',
    'playerDraftYear',
    'playerDraftRoundNo',
    'playerDraftOverallPickNo'
]

for item in data:
    my_data = {field: item[field] for field in fields}
    cur.execute("INSERT INTO t_skaters VALUES (%s)", (json.dumps(my_data),))


# commit changes
conn.commit()
# Close the connection
conn.close()

Não tenho 100% de certeza se toda a sintaxe do postgres está correta aqui (não tenho acesso a um banco de dados PG para testar), mas acredito que essa lógica deve funcionar para o que você está tentando fazer.

Atualização para colunas separadas

Você pode modificar sua instrução create para lidar com várias colunas, mas seria necessário conhecer o tipo de dados de cada coluna. Aqui está algum pseudocódigo que você pode seguir:
# same boilerplate code from above
cur = conn.cursor()
# create a table with one column per field
cur.execute(
"""CREATE TABLE t_skaters (seasonId INTEGER, playerName VARCHAR, ...);"""
)

fields = [
    'seasonId',
    'playerName',
    'playerFirstName',
    'playerLastName',
    'playerId',
    'playerHeight',
    'playerPositionCode',
    'playerShootsCatches',
    'playerBirthCity',
    'playerBirthCountry',
    'playerBirthStateProvince',
    'playerBirthDate',
    'playerDraftYear',
    'playerDraftRoundNo',
    'playerDraftOverallPickNo'
]

for item in data:
    my_data = [item[field] for field in fields]
    # need a placeholder (%s) for each variable 
    # refer to postgres docs on INSERT statement on how to specify order
    cur.execute("INSERT INTO t_skaters VALUES (%s, %s, ...)", tuple(my_data))


# commit changes
conn.commit()
# Close the connection
conn.close()

Substitua o ... com os valores apropriados para seus dados.