Usman Ahmad
Usman Ahmad

Reputation: 416

Insert Nested Objects into mongodb in python3 (Nested object is a class Instance)

I have a nested structure like this:


class Student(object):

    def __init__(self, name, age, address):
        self.name = name
        self.age = age
        self.address = address

class Address(object):

    def __init__(self, street, pcode, another_obj):
        self.street = street
        self.postal_code = pcode
        self.another_obj = another_obj

class AnotherObject(object):

    def __init__(self):
        self.someattr = 'some_init_value'


# Now i amm going to save data like this
another_obj = AnotherObject()
address = Address('xyz', 'xyz', another_obj)
obj = Student('abc', 32, address)

The object obj is an instance of a class. I am doing collection.insert_one(obj). Usually, I would do obj.dict to get "dict" of class instance which is compatible with pymongo but it does not convert the nested objects into dict too. The problem here is that the "address" and "some_other_object" are also some other class instances and that causes bson.errors.InvalidDocument Exception while insertion.

Is there a way to convert nested class instances/documents (address & some_other_object) into dict or any other type acceptable to mongodb.

The package I am using for mongodb communication is pymongo v3.9.0.

Error is TypeError:

document must be an instance of dict, bson.son.SON, bson.raw_bson.RawBSONDocument, or a type that inherits from collections.MutableMapping

Upvotes: 2

Views: 1369

Answers (1)

Belly Buster
Belly Buster

Reputation: 8814

Add in some to_dict() methods to your classes:

from pymongo import MongoClient


class Student(object):

    def __init__(self, name, age, address):
        self.name = name
        self.age = age
        self.address = address

    def to_dict(self) -> dict:
        record = {
            "name": self.name,
            "age": self.age,
            "address": self.address.to_dict() if self.address is not None else None
        }
        return record


class Address(object):

    def __init__(self, street, pcode, another_obj):
        self.street = street
        self.postal_code = pcode
        self.another_obj = another_obj

    def to_dict(self) -> dict:
        record = {
            "street": self.street,
            "postal_code": self.postal_code,
            "another_obj": self.another_obj.to_dict() if self.another_obj is not None else None
        }
        return record


class AnotherObject(object):

    def __init__(self):
        self.someattr = 'some_init_value'

    def to_dict(self) -> dict:
        record = {
            "someattr": self.someattr
        }
        return record


# Now i amm going to save data like this
another_obj = AnotherObject()
address = Address('xyz', 'xyz', another_obj)
obj = Student('abc', 32, address)
db = MongoClient()['yourdatabase']
db.collection.insert_one(obj.to_dict())
print(db.collection.find_one({}))

Upvotes: 1

Related Questions