假设我有一堂课: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
)变成字典,以便可以保存。
答案 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))