MongoEngine - Custom Query Sets



By default, the objects attribute on a document class returns a QuerySet without applying any filter. However, you can define a classmethod on a document that modifies a queryset. Such a method should accept two arguments doc_cls and queryset and it needs to be decorated with queryset_manager() in order for it to be recognized.

@queryset_manager
   def qry_method(docs_cls,queryset):
       .
       ----

In the following example, the document class called products has an expensive_prods() method which is decorated by @queryset_manager. The method itself applies a filter to queryset such that only objects with price >20000 are returned. This method is now the default document query and objects attribute of products class returns filtered documents.

Example - Filtering using Custom Method

main.py

from mongoengine import *

con = connect('myDb')

class Product(Document):
   productID = IntField(required=True)
   name = StringField()
   price = IntField()
   
   @queryset_manager
   def expensive_prods(doc_cls,queryset):
      return queryset.filter(price__gt=20000) 
      
for product in Product.expensive_prods():
   print ("Name:{} price:{}".format(product.name, product.price))

Output

Name:Laptop price:25000
Name:TV price:50000

If you wish to customize methods for filtering documents, first declare a subclass of QuerySet class, and use it as value of queryset_class property in meta dictionary.

The example below uses MyQuerySet class as definition of custom queryset. The myqrymethod() in this class filters the documents whose name field ends with er. In products class, meta attribute refers to this queryset subclass is used as value of queryset_class property.

Example - Filtering using Custom QuerySet

main.py

from mongoengine import *

con=connect('myDb')

class MyQuerySet(QuerySet):
   def myQuery(self):
      return self.filter(name__endswith='top')

class Product (Document):
   meta = {'queryset_class': MyQuerySet}
   productID = IntField(required=True)
   name = StringField()
   price = IntField()
  
for product in Product.objects.myQuery():
   print ("Name:{} price:{}".format(product.name, product.price))

Output

Name:Laptop price:25000
Advertisements