¿Cómo conseguir diccionarios ordenados en pymongo?

Estoy tratando de pedir diccionarios en Pymongo. He leído que se puede hacer con bson.son.Son. Los docs estan aqui

Sin embargo, parece que no puedo hacer que funcione. No hay mucho en google al respecto. Hay algunas discusiones sobre la configuración de pymongo primero para decirle que use objetos SON pero no ejemplos. Un amigo sugirió pasar un param cuando haces un hallazgo. Él no podía recordar.

Soy capaz de crear los objetos SON. Pero cuando se insertan en la base de datos y luego se vuelven a salir, son simples archivos de texto.

No estoy realmente seguro de qué ejemplo de código debo darle porque realmente no sé por dónde empezar. El siguiente fragmento de código crea un objeto SON vacío cada vez que agrego un nuevo usuario. El objeto ‘sub_users’ también fue creado con SON. Cuando leí el documento de cuenta de la base de datos, solo son dicts de python normales.

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

Tal vez un pasado param para encontrar como este para configurar? Esta fue la sugerencia de mis amigos, pero él no podía recordar.

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

¿Algunas ideas?

Puede usar bson.son.SON o OrderedDict para almacenar el OrderedDict ordenado.

Y recuperar datos con as_class=OrderedDict opción as_class=OrderedDict .

Aquí hay un ejemplo:

 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))) 

Salida:

 [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)])] 

Esta solución anterior es correcta para versiones anteriores de MongoDB y el controlador pymongo, pero ya no funciona con pymongo3 y MongoDB3 + Ahora debe agregar document_class=OrderedDict al constructor MongoClient. Modificando la respuesta anterior para compatibilidad con 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}))) 

Salida:

 [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)])] 

Un find () estándar en PyMongo no devolverá un objeto cuyos campos estén en el mismo orden que ese objeto, si lo recuperó a través de mongo shell.

Esto se debe a que el tipo predeterminado devuelto es un Dict y el orden no está definido.

Puedes usar SON como se sugiere. Así es como lo hice. Ahora se respetará el orden de campo.

Esto es para 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'}) 

En PyMongo v3.2, insert() ha quedado en desuso y, en este ejemplo, debe reemplazarse con insert_one() . El código actualizado está abajo:

 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}))) 

Salida:

 [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)])]