PostgreSQL hstore维护存储和检索之间的顺序。这允许您定义存储和检索hstore中的键/值的顺序。
不幸的是,extras.py -> HstoreAdapter.parse() 2的实现使用了一个硬编码的dict。
虽然在大多数情况下,将hstore解析为dict套件很好,但在我们的场景中,这会导致问题;我们特别需要维护排序。
我得出的一个方法是将键和值作为单独的列表进行查询:
SELECT AKEYS(myhstore) AS keys, AVALS(mystoore) AS vals FROM mytbl
..。然而,该解决方案处理的是问题的症状,而不是原因。
是否有人知道针对此问题的猴子补丁解决方案,或处理此问题的psycopg2分支,或解决此问题的extras.py文件的实现?
另外,还有人对如何处理这件事有其他建议吗?
发布于 2013-12-03 18:25:50
注意: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转换为键值对数组的hstore_to_matrix()函数来维护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最终在字典上调用.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
})发布于 2013-12-03 17:59:11
您可以转储到字符串并将其存储为文本。
然后可以在json解码器中指定object_pairs_hook:http://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)])https://stackoverflow.com/questions/20358152
复制相似问题