在Python中使用psycopg2以OrderedDict的形式返回PostgreSQL hstore
PostgreSQL hstore维护存储和检索之间的顺序。这允许用户定义存储和检索hstore中的键/值的顺序 不幸的是,psycopg2的实现使用了在Python中使用psycopg2以OrderedDict的形式返回PostgreSQL hstore,python,postgresql,psycopg2,hstore,Python,Postgresql,Psycopg2,Hstore,PostgreSQL hstore维护存储和检索之间的顺序。这允许用户定义存储和检索hstore中的键/值的顺序 不幸的是,psycopg2的实现使用了extras.py->HstoreAdapter.parse()下的硬编码dict 虽然在大多数场景中,将hstore解析为dict套件都很好,但在我们的场景中,这会导致问题;我们特别需要维持订单 我得出的一个解决方法是将键和值作为单独的列表进行查询: 从mytbl中选择AKEYS(myhstore)作为键,选择AVALS(mytoore)作为V
extras.py->HstoreAdapter.parse()下的硬编码dict
虽然在大多数场景中,将hstore解析为dict套件都很好,但在我们的场景中,这会导致问题;我们特别需要维持订单
我得出的一个解决方法是将键和值作为单独的列表进行查询:
从mytbl中选择AKEYS(myhstore)作为键,选择AVALS(mytoore)作为VAL
。。。但是,该解决方案处理的是问题的症状,而不是原因
有人知道这个问题的猴子补丁解决方案,或者处理这个问题的psycopg2分支,或者解决这个问题的extras.py文件的实现吗
或者,有人对如何处理这个问题有其他建议吗?您可以转储到字符串并存储为文本
然后,您可以在json解码器中指定object\u pairs\u hook
:
注意:不保留秩序。它与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
转换为键值对数组的函数来维护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
最终在将字典转换回HSTORE
时调用字典上的.keys()
和.values()
,这意味着只要对字典进行排序,发送回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
})
您建议以纯文本形式存储,整体放弃hstore数据类型?如果系统的其他部分已经使用了hstore特定的功能,例如键或值的索引,将键/值对作为单独的行返回(使用each()
),或者使用任何其他hstore特定的功能,该怎么办?这个答案假设hstore仅用作存储机制,并且没有使用一个hstore功能;一个非常广泛和危险的假设,“可能”很难成为一个建议。您知道自己的限制,并且在提供所有选项时可以采取最佳方法。
# 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
})