Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Add Range operator to queryset #433

wants to merge 2 commits into from

3 participants


Added a 'range' operator. Works like the one in django:

Since there is no $range operator in MongoDB this is a little hack to make it work in mongoengine.


nice! can you add tests and documentation.


Nice, but is it wise to bring in totally new operators rather than doing it the mongo way eg do a: $gte and a $lte?

If so should we validate what the item passed to __range ?


Good point. I'd be glad to have a native $range operator in MongoDB but for now thats all I can do. I was just playing around with my django project where I use the range operator alot. Probably best would be to have the ability to create custom operators.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 22, 2012
  1. @Raybuntu

    Adding range query operator

    Raybuntu authored
  2. @Raybuntu
This page is out of date. Refresh to see the latest.
1  docs/guide/querying.rst
@@ -64,6 +64,7 @@ Available operators are as follows:
* ``all`` -- every item in list of values provided is in array
* ``size`` -- the size of the array is
* ``exists`` -- value for field exists
+* ``range`` -- in a range of two values (a list or tuple of two values should be provided)
The following operators are available as shortcuts to querying with regular
10 mongoengine/
@@ -619,7 +619,7 @@ def _transform_query(cls, _doc_cls=None, _field_operation=False, **query):
"""Transform a query from Django-style format to Mongo format.
operators = ['ne', 'gt', 'gte', 'lt', 'lte', 'in', 'nin', 'mod',
- 'all', 'size', 'exists', 'not']
+ 'all', 'size', 'exists', 'not', 'range']
geo_operators = ['within_distance', 'within_spherical_distance', 'within_box', 'within_polygon', 'near', 'near_sphere']
match_operators = ['contains', 'icontains', 'startswith',
'istartswith', 'endswith', 'iendswith',
@@ -674,9 +674,15 @@ def _transform_query(cls, _doc_cls=None, _field_operation=False, **query):
value = field
value = field.prepare_query_value(op, value)
- elif op in ('in', 'nin', 'all', 'near'):
+ elif op in ('in', 'nin', 'all', 'near', 'range'):
# 'in', 'nin' and 'all' require a list of values
value = [field.prepare_query_value(op, v) for v in value]
+ if op == 'range':
+ op = False
+ value.sort()
+ min_val = value[0]
+ max_val = value[1]
+ value = {'$gte': min_val, '$lte': max_val}
# if op and op not in match_operators:
if op:
14 tests/
@@ -678,6 +678,20 @@ def test_not(self):
obj = self.Person.objects(name__not__iexact='alice').first()
self.assertEqual(obj, None)
+ def test_range(self):
+ """Ensure that the __range operator works as expected.
+ """
+ self.Person.drop_collection()
+ walker = self.Person(name='Walker', age=50)
+ hugo = self.Person(name='Hugo', age=20)
+ sheldon = self.Person(name='Sheldon', age=38)
+ obj = self.Person.objects(age__range=(20,40))
+ self.assertEqual(obj.count(), 2)
def test_filter_chaining(self):
"""Ensure filters can be chained together.
Something went wrong with that request. Please try again.