diff --git a/docs/changelog.rst b/docs/changelog.rst index 4fd3e143..3e8f7821 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -27,6 +27,7 @@ Changes in 0.8.X - Simplified Q objects, removed QueryTreeTransformerVisitor (#98) (#171) - FileFields now copyable (#198) - Querysets now return clones and are no longer edit in place (#56) +- Added support for $maxDistance (#179) Changes in 0.7.9 ================ diff --git a/docs/guide/querying.rst b/docs/guide/querying.rst index d5829432..40e36e32 100644 --- a/docs/guide/querying.rst +++ b/docs/guide/querying.rst @@ -92,6 +92,8 @@ may used with :class:`~mongoengine.GeoPointField`\ s: * ``within_polygon`` -- filter documents to those within a given polygon (e.g. [(41.91,-87.69), (41.92,-87.68), (41.91,-87.65), (41.89,-87.65)]). .. note:: Requires Mongo Server 2.0 +* ``max_distance`` -- can be added to your location queries to set a maximum +distance. Querying lists diff --git a/mongoengine/queryset/transform.py b/mongoengine/queryset/transform.py index 9fe87802..5707cecb 100644 --- a/mongoengine/queryset/transform.py +++ b/mongoengine/queryset/transform.py @@ -9,7 +9,8 @@ __all__ = ('query', 'update') COMPARISON_OPERATORS = ('ne', 'gt', 'gte', 'lt', 'lte', 'in', 'nin', 'mod', 'all', 'size', 'exists', 'not') GEO_OPERATORS = ('within_distance', 'within_spherical_distance', - 'within_box', 'within_polygon', 'near', 'near_sphere') + 'within_box', 'within_polygon', 'near', 'near_sphere', + 'max_distance') STRING_OPERATORS = ('contains', 'icontains', 'startswith', 'istartswith', 'endswith', 'iendswith', 'exact', 'iexact') @@ -97,6 +98,8 @@ def query(_doc_cls=None, _field_operation=False, **query): value = {'$nearSphere': value} elif op == 'within_box': value = {'$within': {'$box': value}} + elif op == "max_distance": + value = {'$maxDistance': value} else: raise NotImplementedError("Geo method '%s' has not " "been implemented" % op) diff --git a/tests/queryset/queryset.py b/tests/queryset/queryset.py index bf64a565..b5b0b280 100644 --- a/tests/queryset/queryset.py +++ b/tests/queryset/queryset.py @@ -2238,6 +2238,12 @@ class QuerySetTest(unittest.TestCase): self.assertEqual(events.count(), 3) self.assertEqual(list(events), [event3, event1, event2]) + # find events within 10 degrees of san francisco + point = [37.7566023, -122.415579] + events = Event.objects(location__near=point, location__max_distance=10) + self.assertEqual(events.count(), 1) + self.assertEqual(events[0], event2) + # find events within 10 degrees of san francisco point_and_distance = [[37.7566023, -122.415579], 10] events = Event.objects(location__within_distance=point_and_distance) @@ -2317,6 +2323,10 @@ class QuerySetTest(unittest.TestCase): ); self.assertEqual(points.count(), 2) + points = Point.objects(location__near_sphere=[-122, 37.5], + location__max_distance=60 / earth_radius); + self.assertEqual(points.count(), 2) + # Finds both points, but orders the north point first because it's # closer to the reference point to the north. points = Point.objects(location__near_sphere=[-122, 38.5])