Search code examples
pythondata-structurespymongobson

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?


Solution

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