簡體   English   中英

在Python中使用psycopg2將PostgreSQL hstore返回為OrderedDict

[英]Return PostgreSQL hstore as OrderedDict using psycopg2 in Python

PostgreSQL hstore維護存儲和檢索之間的順序。 這樣一來,就可以定義hstore中鍵/值的存儲和檢索順序。

不幸的是,psycopg2的實現在extras.py -> HstoreAdapter.parse()下使用了硬編碼的dict。

在大多數情況下,將hstore解析為dict套件就可以了,但是在我們的情況下,這會引起問題; 我們特別需要保持訂購。

我得出的一種解決方法是,將鍵和值作為單獨的列表進行查詢:

SELECT AKEYS(myhstore) AS keys, AVALS(mystoore) AS vals FROM mytbl

...但是,該解決方案只處理問題的征兆,而不是原因。

有誰知道針對此問題的猴子補丁解決方案,或處理此問題的psycopg2分支,或解決此問題的extras.py文件的實現?

或者,是否有人對如何處理此問題有其他建議?

注意: HSTORE不保留訂單。 它像Python的dict一樣無序。 我以前的回答只是偶然的。

對的順序並不重要(並且可能不會在輸出中復制)。

例:

SELECT 'foo=>1,bar=>2,spam=>3,eggs=>4'::hstore
UNION ALL
SELECT hstore('{foo,1,bar,2,spam,3,eggs,4}'::TEXT[])
UNION ALL
SELECT hstore('{{foo,1},{bar,2},{spam,3},{eggs,4}}'::TEXT[])
UNION ALL
SELECT hstore('{foo,bar,spam,eggs}'::TEXT[], '{1,2,3,4}'::TEXT[])

全部導致:

""bar"=>"2", "foo"=>"1", "eggs"=>"4", "spam"=>"3""
""bar"=>"2", "foo"=>"1", "eggs"=>"4", "spam"=>"3""
""bar"=>"2", "foo"=>"1", "eggs"=>"4", "spam"=>"3""
""bar"=>"2", "foo"=>"1", "eggs"=>"4", "spam"=>"3""

由於它的順序與原始順序不同,並且它不是按字母順序排列的,因此它似乎是無序的。


下列內容無法正常工作!

您可以使用hstore_to_matrix()函數將HSTORE轉換為HSTORE對數組,從而保持HSTORE的順序。 然后,您必須手動將其傳遞給Python中的OrderedDict

import collections
import psycopg2
import psycopg2.extras

pg = psycopg2.connect(...)
psycopg2.extras.register_hstore(pg)
cursor = pg.cursor()

cursor.execute("""
    SELECT hstore_to_matrix('a=>1,b=>2,c=>3'::hstore);
""")
pairs = cursor.fetchone()[0]
ordered = collections.OrderedDict(pairs)

print(pairs)
# [['a', '1'], ['b', '2'], ['c', '3']]
print(ordered)
# OrderedDict([('a', '1'), ('b', '2'), ('c', '3')])

psycopg2轉換回HSTOREpsycopg2最終在字典上調用.keys().values() ,這意味着只要對字典進行了訂購,也HSTORE發送回PostgreSQL的HSTORE進行訂購。 您只需要傳回OrderedDict而不是常規dict即可維持訂單:

# This will save the data as ordered.
data = OrderedDict([('a', '1'), ('b', '2'), ('c', '3')])
cursor.update("""
    UPDATE mytable
    SET ordered = %(data)s;
""", {
    'data': data
})

# This will save the data as unordered. Whatever the internal order
# happens to be for the dict will be sent. When I run it in the python
# interpreter, it results in:
#   [('a', '1'), ('c', '3'), ('b', '2')]
cursor.update("""
    UPDATE mytable
    SET ordered = %(data)s;
""", {
    'data': data
})

你可以轉儲到字符串並存儲為文本

那么您可以在json解碼器中指定object_pairs_hookhttp : //docs.python.org/2/library/json.html#encoders-and-decoders

In [1]: json.JSONDecoder(object_pairs_hook=collections.OrderedDict).decode('{"foo":1, "bar": 2}')
Out[1]: OrderedDict([('foo', 1), ('bar', 2)])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM