如何在pymongo获得有序的词典?

时间:2014-04-10 23:55:00

标签: python data-structures pymongo bson

我正在尝试在Pymongo获得有序的词典。我已经读过它可以用bson.son.Son完成。文档为Here

然而,我似乎无法使其发挥作用。谷歌没有太多关于它。关于配置pymongo的一些讨论首先告诉它使用SON对象但没有例子。一位朋友建议在你找到时传递一个参数。他不记得了。

我可以创建SON对象。但当他们插入数据库然后再回来时,他们只是简单的说法。

我不确定要给你的代码示例是什么,因为我真的不知道从哪里开始。每次添加新用户时,下面的代码段都会创建一个空的SON对象。 'sub_users'对象也是使用SON创建的。当我从数据库中读回帐户文档时,它们只是普通的python dicts。

    account['sub_users'][sub_user_name] = bson.SON()
    with mongo_manager.Collection(CFG.db, 'Users') as users:
        users.save(account)

也许一个param过去找到这样的配置?这是我朋友的建议,但他不记得了。

with mongo_manager.Collection(CFG.db, 'Users') as users:                                 
    account = users.find_one({'_id': _id, 'DOC':'OrderedDict})

有什么想法吗?

4 个答案:

答案 0 :(得分:18)

上述解决方案对于旧版本的MongoDB和pymongo驱动程序是正确的,但它不再适用于pymongo3和MongoDB3 +您现在需要将document_class=OrderedDict添加到MongoClient构造函数中。修改pymongo3兼容性的上述答案。

from collections import OrderedDict
from pymongo import MongoClient
import bson

client = MongoClient(document_class=OrderedDict)
sample_db = client['sample']
test_col = sample_db['test']

test_col.drop()

data = OrderedDict([("one", 1), ("two", 2), ("three", 3), ("four", 4)])
test_col.insert(data)
print(list(test_col.find({}, {'_id': 0})))

test_col.drop()

data = bson.son.SON([("one", 1), ("two", 2), ("three", 3), ("four", 4)])
test_col.insert(data)
print(list(test_col.find({}, {'_id': 0})))

输出:

[OrderedDict([(u'one', 1), (u'two', 2), (u'three', 3), (u'four', 4)])]
[OrderedDict([(u'one', 1), (u'two', 2), (u'three', 3), (u'four', 4)])]

答案 1 :(得分:14)

您可以使用bson.son.SONOrderedDict存储ordereddict。

使用as_class=OrderedDict选项检索数据。

以下是一个例子:

from collections import OrderedDict
from pymongo import MongoClient
import bson

client = MongoClient()
sample_db = client['sample']
test_col = sample_db['test']

test_col.drop()

data = OrderedDict([("one", 1), ("two", 2), ("three", 3), ("four", 4)])
test_col.insert(data)
print(list(test_col.find({}, {'_id': 0}, as_class=OrderedDict)))

test_col.drop()

data = bson.son.SON([("one", 1), ("two", 2), ("three", 3), ("four", 4)])
test_col.insert(data)
print(list(test_col.find({}, {'_id': 0}, as_class=OrderedDict)))

输出:

[OrderedDict([(u'one', 1), (u'two', 2), (u'three', 3), (u'four', 4)])]
[OrderedDict([(u'one', 1), (u'two', 2), (u'three', 3), (u'four', 4)])]

答案 2 :(得分:4)

如果您通过mongo shell检索字段,那么PyMongo中的标准 find()将不会返回字段与该对象的顺序相同的对象。

这是因为,返回的默认类型是Dict,并且未定义顺序。

您可以按照建议使用SON。我就是这样做的。 现在,字段顺序将受到尊重。

这是为pymongo == 3.4.0

from bson.codec_options import CodecOptions
from bson.son import SON

opts = CodecOptions(document_class=SON)
collection_son = mongo.db.collection.with_options(codec_options=opts)

collection_son.find_one({"imsid": '12345'})

答案 3 :(得分:3)

In PyMongo v3.2 insert() has been deprecated and in this example it should be replaced with insert_one(). Updated code is below:

from collections import OrderedDict
from pymongo import MongoClient
import bson

client = MongoClient(document_class=OrderedDict)
sample_db = client['sample']
test_col = sample_db['test']

test_col.drop()

data = OrderedDict([("one", 1), ("two", 2), ("three", 3), ("four", 4)])
test_col.insert_one(data)
print(list(test_col.find({}, {'_id': 0})))

test_col.drop()

data = bson.son.SON([("one", 1), ("two", 2), ("three", 3), ("four", 4)])
test_col.insert_one(data)
print(list(test_col.find({}, {'_id': 0})))

Output:

[OrderedDict([(u'one', 1), (u'two', 2), (u'three', 3), (u'four', 4)])]
[OrderedDict([(u'one', 1), (u'two', 2), (u'three', 3), (u'four', 4)])]