如何将Python对象保存到pymongo中? (即我需要覆盖哪种方法/返回值)

时间:2019-03-29 20:12:51

标签: python pymongo

假设我有一堂课:TestClass。此类已放空。

class TestClass(object):
    __slots__ = ('_id', 'value1', 'value2',)

所以我们创建一个对象。

test = TestClass()
test.key1 = 'val1'
test.key2 = 'val2'

太好了!现在,我要做的是将test插入MongoDB实例中。

db.test_collection.insert(test)

哦哦。

TypeError: 'TestClass' object is not iterable

好,让它变得可迭代。

class TestClass(object):
    __slots__ = ('_id', 'key1', 'key2',)

    def __iter__(self):
        yield from dict(
            (slot, self.__getattribute__(slot))
            for slot in self.__slots__).items()

test = TestClass()
test.key1 = 'val1'
test.key2 = 'val2'

for i in test:
    print(i)

// result
// ('key1', 'val1')
// ('key2', 'val2')

db.test_collection.insert(test)

这给了我doc['_id'] = ObjectId() // TypeError: 'tuple' object does not support item assignment

再说一遍,我有一些物体……

test = TestClass()
test.key1 = 'val1'
test.key2 = TestClass()

保存test.key2时pymongo编码器能否编码test

编辑:我可以不直接保存对象并在对象上调用诸如test.to_document()之类的函数,但是目标是具有复合字段(例如test.key2 )变成字典,以便可以保存。

2 个答案:

答案 0 :(得分:0)

首先,我要问自己,为什么将对象按原样存储在Mongodb中很重要。我想在这里实现什么?

如果对上述问题的回答是:“是的,则有正当的理由”。存储对象的方法是先序列化它们,然后存储该序列化。

泡菜模块可以为您完成此任务。

import pickle

test = TestClass()
dumped = pickle.dumps(test)
db.objects.insert_one({"data": dumped, "name": 'test'})

值得注意的是,因为这些是python对象,并且如果用户无论如何都能将腌制的对象插入数据库中,而您在某个时候解开该对象,则将对您构成安全威胁。

答案 1 :(得分:0)

当您尝试插入单个对象而不是一系列对象时,您收到的第一条错误消息暗示PyMongo期望可迭代,这可能会产生误导。 insert可以使用一个文档(词典),也可以对其进行迭代。

您可以使用function like this将对象转换为字典:

def slotted_to_dict(obj):
    return {s: getattr(obj, s) for s in obj.__slots__ if hasattr(obj, s)}

然后

db.test_collection.insert(slotted_to_dict(test))

应该可以,但是是deprecated。所以

db.test_collection.insert_one(slotted_to_dict(test))

可能更好。

请注意,如果您经常将带槽的对象转换为字典,则可能会因为使用槽而失去任何性能优势。此外,不会在测试对象中设置“ _id”属性,并且您可能需要这样的笨拙解决方案来保存ID:

test._id = db.test_collection.insert_one(slotted_to_dict(test))