Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get ordered dictionaries in pymongo?

I am trying get ordered dictionaries in Pymongo. I have read it can be done with bson.son.Son. The Docs are Here

However, I can't seem to make it work. There is not much on google about it. There are some discussions on configuring pymongo first to tell it to use SON objects but no examples. A friend suggested passing a param when you do a find. He couldn't remember.

I'm able to create the SON objects. But when they get inserted into the DB and then come back out they are just plain dicts.

I'm not sure really what code example to give you because I really don't know where to start. The below snippet creates an empty SON object every time I add a new user. The 'sub_users' object was also created with SON. When I read the account document back from the DB they are just normal python dicts.

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

Maybe a param past to the find like this to configure? This was my friends suggestion but he could not remember.

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

Any ideas?

like image 527
fat fantasma Avatar asked Apr 10 '14 23:04

fat fantasma


People also ask

Are Dictionaries ordered Python?

As of Python version 3.7, dictionaries are ordered. In Python 3.6 and earlier, dictionaries are unordered. When we say that dictionaries are ordered, it means that the items have a defined order, and that order will not change.

How is ordered dict implemented in Python?

Python's OrderedDict is a dict subclass that preserves the order in which key-value pairs, commonly known as items, are inserted into the dictionary. When you iterate over an OrderedDict object, items are traversed in the original order. If you update the value of an existing key, then the order remains unchanged.

Is dictionary ordered collection?

Dictionary in Python is an unordered collection of data values, used to store data values like a map, which unlike other Data Types that hold only single value as an element, Dictionary holds key:value pair.

Does dict maintain order?

Standard dict objects preserve order in the reference (CPython) implementations of Python 3.5 and 3.6, and this order-preserving property is becoming a language feature in Python 3.7.


2 Answers

This solution above is correct for older versions of MongoDB and the pymongo driver but it no longer works with pymongo3 and MongoDB3+ You now need to add document_class=OrderedDict to the MongoClient constructor. Modifying the above answer for pymongo3 compatibility.

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

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)])]
like image 199
Alan Viars Avatar answered Sep 23 '22 05:09

Alan Viars


You can use bson.son.SON or OrderedDict to store ordered dict.

And retrive data with as_class=OrderedDict option.

Here is an example:

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

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)])]
like image 30
Omid Raha Avatar answered Sep 24 '22 05:09

Omid Raha