Skip to content

EmbeddedDocumentField errors during update when adding new field to DynamicEmbeddedDocument #2486

Open
@mcsimps2

Description

@mcsimps2

Summary: When using a DynamicEmbeddedDocument, an InvalidQueryError occurs if you try to set a field that is not defined in the MongoEngine schema. This invalidates the purpose of a dynamic document.

Example:

class B(DynamicEmbeddedDocument):
   foo = StringField()

class A(Document):
  b = EmbeddedDocumentField(B)

# This works
A.objects(...).update(set__b__foo="123")

# This does not work
A.objects(...).update(set__b__bar="123")
# mongoengine.errors.InvalidQueryError: Cannot resolve field "bar"

Solution:
In my custom fork of MongoEngine, I've updated the EmbeddedDocumentField to account for dynamic documents as such.

class EmbeddedDocumentField(BaseField):
      def lookup_member(self, member_name):
        doc_and_subclasses = [self.document_type] + self.document_type.__subclasses__()
        for doc_type in doc_and_subclasses:
            field = doc_type._fields.get(member_name)
            if field:
                return field
        # NEW CODE
        if member_name not in ("S", "$") and any(issubclass(doc_type, DynamicEmbeddedDocument) for doc_type in doc_and_subclasses):
           return DynamicField(db_field=member_name)

Custom Situation: I encountered this error because I had a EmbeddedDocumentListField of DynamicEmbeddedDocuments and I was trying to perform array operators like so:

A.objects(b__foo="abc").modify(set__list_of_b__S__bar="123")

If the maintainers find my solution acceptable, I would be happy to write tests and make a PR with it. Otherwise, I will defer to coders with greater expertise in this codebase for the proper strategy here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions