Как получить упорядоченные словари в пимонго?
Я пытаюсь получить упорядоченные словари в Pymongo. Я прочитал, что это можно сделать с помощью bson.son.Son. Документы Здесь
Однако я не могу заставить его работать. Об этом не так много говорится в google. Есть несколько обсуждений по настройке pymongo сначала, чтобы сказать, что он использует объекты SON, но нет примеров. Друг предложил передать парам, когда вы найдете находку. Он не мог вспомнить.
Я могу создать объекты SON. Но когда они вставляются в БД и затем возвращаются, они просто простые dicts.
Я не уверен, какой код кода вам дать, потому что я действительно не знаю, с чего начать. Следующий сниппет создает пустой объект 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})
Любые идеи?
Ответы
Ответ 1
Вы можете использовать bson.son.SON
или OrderedDict
для хранения упорядоченного dict.
И извлеките данные с опцией 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
Это решение выше для старых версий 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)])]
Ответ 3
Стандартная find() в PyMongo не вернет объект, поля которого находятся в том же порядке, что и этот объект, если вы его извлекли через оболочку mongo.
Это связано с тем, что возвращаемый по умолчанию тип 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'})
Ответ 4
В PyMongo v3.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)])]