如何在pymongo中获取有序字典?
我想在Pymongo中使用有序字典。我听说可以用bson.son.Son来实现。相关文档可以在这里找到。
不过,我似乎无法让它正常工作。网上关于这个的资料不多。有些讨论提到要先配置pymongo,让它使用SON对象,但没有具体的例子。我的一个朋友建议在进行查找时传递一个参数,但他记不清具体是什么了。
我能创建SON对象,但当它们插入数据库后再取出来时,变成了普通的字典。
我其实不太确定该给你什么代码示例,因为我不知道从哪里开始。下面这段代码每次添加新用户时都会创建一个空的SON对象。'sub_users'对象也是用SON创建的。当我从数据库中读取账户文档时,它们只是普通的Python字典。
account['sub_users'][sub_user_name] = bson.SON()
with mongo_manager.Collection(CFG.db, 'Users') as users:
users.save(account)
也许可以像这样在查找时传递一个参数来配置?这是我朋友的建议,但他记不清了。
with mongo_manager.Collection(CFG.db, 'Users') as users:
account = users.find_one({'_id': _id, 'DOC':'OrderedDict})
有什么想法吗?
4 个回答
在PyMongo版本3.2中,insert()
这个方法已经不再推荐使用了。在这个例子中,应该用insert_one()
来替代它。下面是更新后的代码:
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})))
输出结果:
[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)])]
在PyMongo中,标准的find()方法不会返回一个字段顺序和你在mongo shell中获取的对象相同的对象。
这是因为,默认返回的类型是字典(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'})
上面的解决方案适用于旧版本的MongoDB和pymongo驱动,但在pymongo3和MongoDB3以上的版本中就不再适用了。现在你需要在MongoClient的构造函数中添加 document_class=OrderedDict
。这样才能让上面的答案在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)])]
你可以使用 bson.son.SON
或者 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)])]