Search code examples
pythonmongodbmongodb-querymongoengine

Query by computed property in python mongoengine


I wondered if it is possible to query documents in MongoDB by computed properties using mongoengine in python.

Currently, my model looks like this:

class SnapshotIndicatorKeyValue(db.Document):
    meta = {"collection": "snapshot_indicator_key_values"}

    snapshot_id = db.ObjectIdField(nullable=False)
    indicator_key_id = db.ObjectIdField(nullable=False)
    value = db.FloatField(nullable=False)
    created_at = db.DateTimeField()
    updated_at = db.DateTimeField()

    @property
    def snapshot(self):
        return Snapshot.objects(id=self.snapshot_id).first()

    def indicator_key(self):
        return IndicatorKey.objects(id=self.indicator_key_id).first()

When I do for example SnapshotIndicatorKeyValue .objects().first().snapshot, I can access the snapshotproperty.

But when I try to query it, it doesn't work. For example:

SnapshotIndicatorKeyValue.objects(snapshot__date_time__lte=current_date_time)

I get the error `mongoengine.errors.InvalidQueryError: Cannot resolve field "snapshot"``

Is there any way to get this working with queries? I need to query SnapshotIndicatorKeyValue based on a property of snapshot.


Solution

  • In order to query the snapshot property directly through mongoengine, you can reference the related snapshot object rather than the snapshot_id in your SnapshotIndicatorKeyValue document definition.

    An amended model using a Reference field would be like this:

    from mongoengine import Document, ReferenceField
    
    class Snapshot(Document)
    property_abc = RelevantPropertyHere() # anything you need
    
    class SnapshotIndicatorKeyValue(Document):
    snapshot = ReferenceField(Snapshot)
    

    You would sucessively save an instance of Snapshot and an instance of SnapshotIndicatorKeyValue like this:

    sample_snapshot = Snapshot(property_abc=relevant_value_here) # anything you need
    sample_snapshot.save()
    
    sample_indicatorkeyvalue = SnapshotIndicatorKeyValue()
    sample_indicatorkeyvalue.snapshot = sample_snapshot
    sample_indicatorkeyvalue.save()
    

    You can then refer to any of the snapshot's properties through:

    SnapshotIndicatorKeyValue.objects.first().snapshot.property_abc