Open
Description
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 DynamicEmbeddedDocument
s 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
Labels
No labels