web-dev-qa-db-ja.com

postgresqlへのdictオブジェクトの追加

そのため、Python3.5でpsycopg2を使用して、postgresqlデータベースにデータを挿入しています。私がやりたいのは、文字列である2つの列があり、最後の列がdictオブジェクトであるということです。 dictを検索する必要はありません。データベースから取り出して、使用することができます。

たとえば:

uuid = "testName"
otherString = ""
dict = {'id':'122','name':'test','number':'444-444-4444'}

# add code here to store two strings and dict to postgresql

cur.execute('''SELECT dict FROM table where uuid = %s''', 'testName')
newDict = cur.fetchone()
print(newDict['number'])

これは可能ですか?もしそうなら、どうすればこれを行うことができますか?

6
sbeyeler

PostgreSQLのバージョンが十分に新しく(9.4以降)、psycopgのバージョンが2.5.4以上の場合、すべてのキーが文字列であり、値をJSONとして表すことができる場合は、これをJSONB列に格納するのが最適です。その後、必要に応じて、列も検索可能になります。単純に次のようにテーブルを作成します

CREATE TABLE thetable (
    uuid TEXT,
    dict JSONB
);

(...そして必要に応じてインデックスや主キーなどを自然に追加します...)辞書をPostgreSQLに送信するときは、 Json アダプタでラップする必要があります。 PostgreSQLから受信すると、JSONB値は自動的に辞書に変換されるため、挿入すると次のようになります。

from psycopg2.extras import Json, DictCursor

cur = conn.cursor(cursor_factory=DictCursor)

cur.execute('INSERT into thetable (uuid, dict) values (%s, %s)',
    ['testName', Json({'id':'122','name':'test','number':'444-444-4444'})])

選択は簡単です

cur.execute('SELECT dict FROM thetable where uuid = %s', ['testName'])
row = cur.fetchone()
print(row['dict']) # its now a dictionary object with all the keys restored
print(row['dict']['number']) # the value of the number key

JSONBを使用すると、PostgreSQLは、辞書をテキストとしてダンプするよりも効率的に値を格納できます。さらに、データを使用してクエリを実行することが可能になります。たとえば、JSONB列からいくつかのフィールドを選択するだけです。

>>> cur.execute("SELECT dict->>'id', dict->>'number' FROM thetable")
>>> cur.fetchone()
['122', '444-444-4444']

または、必要に応じてクエリで使用できます。

>>> cur.execute("SELECT uuid FROM thetable WHERE dict->>'number' = %s',
    ['444-444-4444'])
>>> cur.fetchall()
[['testName', {'id': '122', 'name': 'test', 'number': '444-444-4444'}]]
13
Antti Haapala

データを保存する前に、JSONを使用してデータをシリアル化できます。

import json

data = json.dumps({'id':'122','name':'test','number':'444-444-4444'})

次に、コードを取得するときに、コードを逆シリアル化します。

cur.execute('SELECT dict from ....')
res = cur.fetchone()

dict = json.loads(res['dict'])
print(dict['number'])
2
Andre Barbosa