Mongoengine: .only() not working as expected on reference fields

Created on 17 Nov 2015  路  4Comments  路  Source: MongoEngine/mongoengine

In-reference too:
http://docs.mongoengine.org/en/latest/apireference.html#mongoengine.queryset.QuerySet.only

It looks like .only( should work for reference fields to get a reference subfield result.
Am I mis-interpreting the documentation and this will only work for embedded fields or other field types?

Subnet.objects().only('related_interface.description')

or

Subnet.objects().only('related_interface__description')

Results in:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/site-packages/mongoengine/queryset/base.py", line 789, in only
    return self.fields(True, **fields)
  File "/usr/lib/python2.6/site-packages/mongoengine/queryset/base.py", line 843, in fields
    fields = queryset._fields_to_dbfields(fields)
  File "/usr/lib/python2.6/site-packages/mongoengine/queryset/base.py", line 1644, in _fields_to_dbfields
    raise err
mongoengine.errors.LookUpError: Cannot perform join in mongoDB: related_interface__description

Any suggestions would be appreciated.

(De)Reference Enhancement

Most helpful comment

I support adding this as a feature.
It seems very intuitive.
+1 from me

All 4 comments

I think the issue here is that the only() method simply changes the query that is sent to the db. It does not claim to perform adjustments to the de-referencing that may happen with the returned documents.

Because on the db a ReferenceField is just an ObjectID there is no knowledge of the structure of any documents that is referenced.

The error you are seeing is Mongoengine telling you that the operation doesn't get the referenced document (as an JOIN operation in SQL could).

The main use for the onlymethod is to reduce the amount of traffic between db and client by only returning what you need. If you are having issues with large reference documents being dereferenced then look at the no_dereference context manager to help you out.

So

  • If you want to limit the document fields that are returned from the DB, you use only
  • If you want to avoid fetching a complete referenced document, you use no_dereference
  • If you want to limit the document fields of a referenced document, then you can't do that in one shot, you need to use 'no_dereference', then launch another query on the referenced document using only.

Is that it?

Maybe MongoEngine could extend only or provide a syntax to apply only-like field masking to referenced documents, like what the OP suggests:

Subnet.objects().only('related_interface.description')

Subnet.objects().only('related_interface__description')

Maybe more of a feature request than a bug, then.

I support adding this as a feature.
It seems very intuitive.
+1 from me

I strongly support adding this feature as I need it for a project which involves extracting one or two string fields from a referenced object that also contains other fields that are extremely large. Currently, I am using select_related(), however, this dereferences everything leading to extremely slow response times.

Was this page helpful?
0 / 5 - 0 ratings