web-dev-qa-db-ja.com

JSONをSQLiteにPython-jsonキーをデータベース列に適切にマッピングする方法は?

作成したJSONファイルをSQLiteデータベースに変換したい。

私の意図は、json(テキストエディターを介したデータ入力)またはSQLite(SQLiteStudioなどのスプレッドシートのようなGUIを介したデータ入力)のどちらが最適かを後で決定することです。

私のjsonファイルは次のようなものです(私の都市のいくつかの交差点からの交通データが含まれています):

_...
"2011-12-17 16:00": {
    "local": "Av. Protásio Alves; esquina Ramiro Barcelos",
    "coord": "-30.036916,-51.208093",
    "sentido": "bairro-centro",
    "veiculos": "automotores",
    "modalidade": "semaforo 50-15",
    "regime": "típico",
    "pistas": "2+c",
    "medicoes": [
        [32, 50],
        [40, 50],
        [29, 50],
        [32, 50],
        [35, 50]
        ]
    },
"2011-12-19 08:38": {
    "local": "R. Fernandes Vieira; esquina Protásio Alves",
    "coord": "-30.035535,-51.211079",
    "sentido": "único",
    "veiculos": "automotores",
    "modalidade": "semáforo 30-70",
    "regime": "típico",
    "pistas": "3",
    "medicoes": [
        [23, 30],
        [32, 30],
        [33, 30],
        [32, 30]
        ]
    }
...
_

そして、私はPythonコードのこれらの行と1対多の関係を持つNiceデータベースを作成しました:

_import sqlite3

db = sqlite3.connect("fluxos.sqlite")
c = db.cursor()

c.execute('''create table medicoes
         (timestamp text primary key,
          local text,
          coord text,
          sentido text,
          veiculos text,
          modalidade text,
          pistas text)''')

c.execute('''create table valores
         (id integer primary key,
          quantidade integer,
          tempo integer,
          foreign key (id) references medicoes(timestamp))''')
_

しかし、問題は、c.execute("insert into medicoes values(?,?,?,?,?,?,?)" % keys)のような実際のデータを含む行を挿入する準備をしているときに、JSONファイルからロードされたdictには特別な順序がないため、適切にマッピングされないことですデータベースの列順序。

だから、私は尋ねる:「JSONファイルの各「ブロック」からキーをプログラムで読み取るためにどの戦略/方法を使用すべきか(この場合、「local」、「coord」、「sentido」、「veiculos」、「modalidade "、" regime "、" pistas "e" medicoes ")、同じ順序で列を持つデータベースを作成し、適切な値を持つ行を挿入します"?

私はPythonでかなりの経験を持っていますが、SQLを始めたばかりです。そのため、必ずしもすぐに使えるレシピとは限らず、良い習慣についてカウンセリングをしたいと思います。

44
heltonbiker

あなたはこれを持っていますpythonコード:

c.execute("insert into medicoes values(?,?,?,?,?,?,?)" % keys)

私はそうすべきだと思う

c.execute("insert into medicoes values (?,?,?,?,?,?,?)", keys)

% operator は、左側の文字列にフォーマットコードが含まれることを想定しています。

この作業を行うために必要なことは、keysがmedicoesテーブルの新しい行の値を正しい順序で含むタプル(またはリスト)になることだけです。次のpythonコードを考慮してください:

import json

traffic = json.load(open('xxx.json'))

columns = ['local', 'coord', 'sentido', 'veiculos', 'modalidade', 'pistas']
for timestamp, data in traffic.iteritems():
    keys = (timestamp,) + Tuple(data[c] for c in columns)
    print str(keys)

サンプルデータでこれを実行すると、次の結果が得られます。

(u'2011-12-19 08:38', u'R. Fernandes Vieira; esquina Prot\xe1sio Alves', u'-30.035535,-51.211079', u'\xfanico', u'automotores', u'sem\xe1foro 30-70', u'3')
(u'2011-12-17 16:00', u'Av. Prot\xe1sio Alves; esquina Ramiro Barcelos', u'-30.036916,-51.208093', u'bairro-centro', u'automotores', u'semaforo 50-15', u'2+c')

必要なタプルのようです。

次のようなもので必要なsqliteコードを追加できます。

import json
import sqlite3

traffic = json.load(open('xxx.json'))
db = sqlite3.connect("fluxos.sqlite")

query = "insert into medicoes values (?,?,?,?,?,?,?)"
columns = ['local', 'coord', 'sentido', 'veiculos', 'modalidade', 'pistas']
for timestamp, data in traffic.iteritems():
    keys = (timestamp,) + Tuple(data[c] for c in columns)
    c = db.cursor()
    c.execute(query, keys)
    c.close()

編集:列のリストをハードコーディングしたくない場合は、次のようにすることができます:

import json

traffic = json.load(open('xxx.json'))

someitem = traffic.itervalues().next()
columns = list(someitem.keys())
print columns

これを実行すると、次のように出力されます:

[u'medicoes', u'veiculos', u'coord', u'modalidade', u'sentido', u'local', u'pistas', u'regime']

次のようなもので使用できます。

import json
import sqlite3

db = sqlite3.connect('fluxos.sqlite')
traffic = json.load(open('xxx.json'))

someitem = traffic.itervalues().next()
columns = list(someitem.keys())
columns.remove('medicoes')
columns.remove('regime')

query = "insert into medicoes (timestamp,{0}) values (?{1})"
query = query.format(",".join(columns), ",?" * len(columns))
print query

for timestamp, data in traffic.iteritems():
    keys = (timestamp,) + Tuple(data[c] for c in columns)
    c = db.cursor()
    c.execute(query)
    c.close()

サンプルコードで試してみると、このコードが出力するクエリは次のようになります。

insert into medicoes (timestamp,veiculos,coord,modalidade,sentido,local,pistas) values (?,?,?,?,?,?,?)
44
srgerg