首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用PostgreSQL中的psycopg2将psycopg2作为OrderedDict返回psycopg2

使用PostgreSQL中的psycopg2将psycopg2作为OrderedDict返回psycopg2
EN

Stack Overflow用户
提问于 2013-12-03 17:49:40
回答 2查看 2.9K关注 0票数 1

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文件的实现?

另外,还有人对如何处理这件事有其他建议吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-03 18:25:50

注意:HSTORE不保留顺序。它是无序的,就像Python的dict。我以前的回答只是偶然的。

对的顺序不显着(并且不能在输出上再现)。

示例:

代码语言:javascript
复制
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[])

所有的结果都是:

代码语言:javascript
复制
""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

代码语言:javascript
复制
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,就可以维持秩序:

代码语言:javascript
复制
# 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
})
票数 2
EN

Stack Overflow用户

发布于 2013-12-03 17:59:11

您可以转储到字符串并将其存储为文本。

然后可以在json解码器中指定object_pairs_hookhttp://docs.python.org/2/library/json.html#encoders-and-decoders

代码语言:javascript
复制
In [1]: json.JSONDecoder(object_pairs_hook=collections.OrderedDict).decode('{"foo":1, "bar": 2}')
Out[1]: OrderedDict([('foo', 1), ('bar', 2)])
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20358152

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档