Skip to content
This repository has been archived by the owner on Jul 14, 2020. It is now read-only.

Embedded SchemaDocument types don't get re-instantiated when querying data from Mongo #157

Open
shahafabileah opened this issue Dec 6, 2013 · 2 comments
Labels

Comments

@shahafabileah
Copy link

Here's repro code (taken from https://friendpaste.com/2kZCdnwpbuOREzQHmTSurB, posted there by someone else):

from mongokit import Connection,Document,SchemaDocument
from pprint import pprint

connection = Connection('localhost',27017)

@connection.register
class Embed(SchemaDocument):

    structure = {
        'dummy': basestring
    }

    use_dot_notation = True

@connection.register
class Doc(Document):
    __database__ = 'test'
    __collection__ = 'docs'

    structure = {
        'embed': Embed
    }

    use_dot_notation = True

# We insert in db...
doc = connection.Doc()
embed = Embed()
embed.dummy = 'dummy'

doc.embed = embed
doc.save()

#We fetch from db...
doc = connection.Doc.find_one()

print(type(doc))
print(type(doc.embed))

# The result of the print command is
# <class '__main__.Doc'>
# <type 'dict'>

So, we can use the Embed class when we first instantiate our Doc and store it in Mongo. But when we query the Doc back out, it no longer has Embed instances, just plain old dict's. This matters because the Embed class might have helper methods that we want to use.

I took a brief look through mongokit's code:

  • document.py, Document.find_one calls collection.find_one and passes in self._obj_class
  • collection.py, Collection.find_one creates a Cursor and passes all args in
  • cursor.py, the Cursor's next method does the work to wrap the son
  • schema_document.py, the actual wrapping is a shallow copy in SchemaDocument's __init__:
        if doc:
            for k, v in doc.iteritems():
                self[k] = v

So, it looks like the mechanism exists to convert a plain dictionary to a specific type, but this is only applied at the top level, not for any embedded SchemaDocuments within.

Is that correct?

If so, I propose to change the behavior. We have the full structure so we can identify types that inherit from SchemaDocument. We can find those items in the son and wrap them as well. Of course there's a performance penalty for this, so it would help to keep track of whether a given class has any embedded SchemaDocument types at all (which we can do when we first validate the Document's structure). It might be useful to add a flag to turn this behavior on/off.

What do you think?

@namlook
Copy link
Owner

namlook commented Dec 10, 2013

Hi,

You are right, the embed mechanism act only with schema and not methods.

This is a good idea. As you said, a flag to turn this turn this behavior on/off is necessary. Unfortunately, I really don't have the time to implement it. Maybe you can and make a pull request ? If so, please add intensives tests and good documentation to ease the code review.

Thanks !

Edit: I just see your proposal. I'll read it.

@shahafabileah
Copy link
Author

Thanks for the reply!

I found that MongoEngine has this capability built-in, so for now my team decided to use that library instead of MongoKit.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants