【问题标题】:How to get ordered dictionaries in pymongo?如何在 pymongo 中获取有序字典?
【发布时间】:2014-05-24 22:25:03
【问题描述】:

我正在尝试在 Pymongo 中获取有序字典。我读过它可以用 bson.son.Son 完成。文档是Here

但是,我似乎无法让它工作。谷歌上没有太多关于它的信息。有一些关于首先配置 pymongo 以告诉它使用 SON 对象的讨论,但没有示例。一位朋友建议您在进行查找时传递一个参数。他不记得了。

我能够创建 SON 对象。但是当它们被插入到数据库中然后又出来时,它们只是普通的 dicts。

我不确定该给你什么代码示例,因为我真的不知道从哪里开始。每次添加新用户时,下面的 sn-p 都会创建一个空的 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})

有什么想法吗?

【问题讨论】:

    标签: python data-structures pymongo bson


    【解决方案1】:

    如果您通过 mongo shell 检索它,PyMongo 中的标准 find() 将不会返回字段顺序与该对象相同的对象。

    这是因为,返回的默认类型是 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'})
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        上述解决方案适用于旧版本的 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)])]
        

        【讨论】:

          【解决方案4】:

          您可以使用bson.son.SONOrderedDict 来存储有序字典。

          并使用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)])]
          

          【讨论】:

          • 使用OrderedDictSON 对象在性能上有什么区别吗?查看源代码(herehere),它们都是 dict 的子类,但 OrderedDict 有一个 C 实现(使用纯 Python 作为后备),而 SON 似乎只有一个 Python 实现...
          • 我收到错误消息 - “__init__() 有一个意外的关键字参数 'as_class'”。
          • @KalyanamRajashree 这是因为它已被删除
          猜你喜欢
          • 2016-08-08
          • 1970-01-01
          • 1970-01-01
          • 2016-09-16
          • 2021-10-23
          • 1970-01-01
          • 2011-11-01
          • 1970-01-01
          相关资源
          最近更新 更多