MongoEngine / MongoEngine/mongoengine

InvalidDocument when using EmbeddedDocument primary key and ReferenceField

Open
#2,778 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
4.3k
Forks
1.2k
Avg merge
4h 41m
Merged PRs (30d)
11

Description

The mongoengine documentation states that EmbeddedDocuments support being the primary_key, which is true, but this breaks if you try to create a ReferenceField pointing to such a document. Consider the following:

import mongoengine as me
from bson import ObjectId

class IdTag(me.EmbeddedDocument):
    id = me.ObjectIdField(default=ObjectId)
    tag = StringField(default='')

class VersionedDocument(me.Document):
    id = me.EmbeddedDocumentField(IdTag, default=IdTag, primary_key=True)
    meta = {'abstract': True}

class A(VersionedDocument):
    name = me.StringField()

class B(VersionedDocument):
    name = me.StringField()
    a = me.ReferenceField(A)

> a1 = A(name="a1").save()
> b1 = B(name="b1", a=a1).save()
> B.objects.get().a

This raises an InvalidDocument exception during dereferencing. Pymongo uses the id of the dbref directly in a query:

return self[dbref.collection].find_one({"_id": dbref.id}, session=session, **kwargs)

The relevant call in mongoengine is Line 1178 in fields.py

dereferenced_son = ref_cls._get_db().dereference(dbref)

I think this could be universally fixed with

dereferenced_son = ref_cls._get_db().dereference(DBRef(dbref.collection, dbref.id.to_mongo())

Unless dbref.id is not always a field, in which case a try..except should work

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in mongoengine/fields.py at line 1178 and reproduce the InvalidDocument with the EmbeddedDocument primary key and ReferenceField example. Compare the dbref handling there with PyMongo's dereference call. Done means B.objects.get().a dereferences successfully without InvalidDocument, with coverage for the reported case.

Written by the indexing model from the issue text.

Assessment

Tech stack
mongodb, python
Domain
database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.