mongokit icon indicating copy to clipboard operation
mongokit copied to clipboard

allow circular references

Open namlook opened this issue 14 years ago • 5 comments

As auto referencing is currently implement, there can be no circular references. This is not allowed currently: Doc1 referencing Doc2 and Doc2 referencing Doc1 Circular references are common in graph data structures. Currently, to implement circular references the user needs to implement their own dbref functions, and can not use the mongokit's auto referencing feature. Graphs are a common data structure as can be seen in the numerous non-sql graph databases. Adding the ability to handle circular references in mongokit would greatly enhance its usefulness.

namlook avatar Oct 20 '10 09:10 namlook

+1

pferreir avatar Jun 05 '12 11:06 pferreir

Still, I am not using auto-referencing and this doesn't seem to work eiter:

from mongokit import Connection, Document

conn = Connection()
db = conn.test3

class Talk(Document):
    __collection__ = 'talks'
    structure = {
        'title': unicode,
        'speakers': []
        }

class Speaker(Document):
    __collection__ = 'speakers'
    structure = {
        'name': unicode,
        'talks': []
        }

conn.register([Talk, Speaker])

if __name__ == '__main__':
    s = db.Speaker({'name': 'bob'})
    t = db.Talk({'title': 'talk 1', 'speakers': [s]})
    s['talks'] = [t]
    s.save()
    t.save()

Error:

RuntimeError: maximum recursion depth exceeded while encoding an object to BSON

pferreir avatar Jun 05 '12 11:06 pferreir

+1

Actually.. since this bug (what @pferreir posted) is open for two years now: Should this project be considered inactive/dead? It seems to be nice but having references between two documents is one of the most basic things...

ThiefMaster avatar Apr 15 '14 18:04 ThiefMaster

A simple workaround is to pass the _id instead of the object:

from mongokit import Connection, Document

conn = Connection()
db = conn.test3

class Talk(Document):
    __collection__ = 'talks'
    structure = {
        'title': unicode,
        'speakers': []
        }

class Speaker(Document):
    __collection__ = 'speakers'
    structure = {
        'name': unicode,
        'talks': []
        }

conn.register([Talk, Speaker])

if __name__ == '__main__':
    s = db.Speaker({'name': 'bob'})
    t = db.Talk({'title': 'talk 1', 'speakers': [s['_id']]})
    s['talks'] = [t['_id']]
    s.save()
    t.save()

This would do the trick and is fast.

Feel free to make a pull request to fix this issue. Note that it has to be very tested as it touches Mongokit's core...

namlook avatar Apr 16 '14 09:04 namlook

I tried this yesterday evening in my own application and the while it "worked", I ended up getting a plain dict instead of the proper instance for the referenced object. I'm at work right now but I can probably create a minimal testcase reproducing that problem and file it as a separate issue later today.

ThiefMaster avatar Apr 16 '14 09:04 ThiefMaster