2

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

1
  • Show the class. Please read how to ask Commented Sep 17, 2019 at 5:34

1 Answer 1

1

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({}))
Sign up to request clarification or add additional context in comments.

2 Comments

what if "self.another_obj" in Address class is a list of objects, Am I going to need to call to_dict() upto the length of self.another_obj? Isn't it going to be inefficient as I am dealing with a significant amount of data?
Please read this stackoverflow.com/help/someone-answers. If you have another specific issue raise a separate question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.