From 376ca717fa53bd010a834d1fbd30d535ec018529 Mon Sep 17 00:00:00 2001 From: John Arnfield Date: Sat, 30 Jul 2011 22:01:24 +0100 Subject: [PATCH 1/5] Added support for within_polygon for spatial queries --- mongoengine/queryset.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mongoengine/queryset.py b/mongoengine/queryset.py index 0af8dead..5ceeea9d 100644 --- a/mongoengine/queryset.py +++ b/mongoengine/queryset.py @@ -481,7 +481,7 @@ class QuerySet(object): """ operators = ['ne', 'gt', 'gte', 'lt', 'lte', 'in', 'nin', 'mod', 'all', 'size', 'exists', 'not'] - geo_operators = ['within_distance', 'within_spherical_distance', 'within_box', 'near', 'near_sphere'] + geo_operators = ['within_distance', 'within_spherical_distance', 'within_box', 'within_polygon', 'near', 'near_sphere'] match_operators = ['contains', 'icontains', 'startswith', 'istartswith', 'endswith', 'iendswith', 'exact', 'iexact'] @@ -527,6 +527,8 @@ class QuerySet(object): value = {'$within': {'$center': value}} elif op == "within_spherical_distance": value = {'$within': {'$centerSphere': value}} + elif op == "within_polygon": + value = {'$within': {'$polygon': value}} elif op == "near": value = {'$near': value} elif op == "near_sphere": From ca3b004921fd9e69ab0a3d3b6b62a435826c26a5 Mon Sep 17 00:00:00 2001 From: John Arnfield Date: Wed, 17 Aug 2011 20:04:38 +0100 Subject: [PATCH 2/5] Added tests for polygon queries --- tests/queryset.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/queryset.py b/tests/queryset.py index 72623b89..778d9317 100644 --- a/tests/queryset.py +++ b/tests/queryset.py @@ -1355,6 +1355,26 @@ class QuerySetTest(unittest.TestCase): self.assertEqual(events.count(), 1) self.assertEqual(events[0].id, event2.id) + # check that polygon works + polygon = [ + (41.912114,-87.694445), + (41.919395,-87.69084), + (41.927186,-87.681742), + (41.911731,-87.654276), + (41.898061,-87.656164), + ] + events = Event.objects(location__within_polygon=polygon) + self.assertEqual(events.count(), 1) + self.assertEqual(events[0].id, event1.id) + + polygon2 = [ + (54.033586,-1.742249), + (52.792797,-1.225891), + (53.389881,-4.40094) + ] + events = Event.objects(location__within_polygon=polygon2) + self.assertEqual(events.count(), 0) + Event.drop_collection() def test_spherical_geospatial_operators(self): From 88cb8f39638c99860b81cb299df9409d17a91624 Mon Sep 17 00:00:00 2001 From: John Arnfield Date: Wed, 17 Aug 2011 20:14:24 +0100 Subject: [PATCH 3/5] left some conflict markers in - oops --- mongoengine/queryset.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/mongoengine/queryset.py b/mongoengine/queryset.py index 397a1538..a715b57d 100644 --- a/mongoengine/queryset.py +++ b/mongoengine/queryset.py @@ -617,15 +617,9 @@ class QuerySet(object): """ operators = ['ne', 'gt', 'gte', 'lt', 'lte', 'in', 'nin', 'mod', 'all', 'size', 'exists', 'not'] -<<<<<<< HEAD - geo_operators = ['within_distance', 'within_spherical_distance', 'within_box', 'near', 'near_sphere'] + geo_operators = ['within_distance', 'within_spherical_distance', 'within_box', 'within_polygon' 'near', 'near_sphere'] match_operators = ['contains', 'icontains', 'startswith', 'istartswith', 'endswith', 'iendswith', -======= - geo_operators = ['within_distance', 'within_spherical_distance', 'within_box', 'within_polygon', 'near', 'near_sphere'] - match_operators = ['contains', 'icontains', 'startswith', - 'istartswith', 'endswith', 'iendswith', ->>>>>>> master 'exact', 'iexact'] mongo_query = {} From 10bc93dfa64e146e64077e12aa29412139bd436f Mon Sep 17 00:00:00 2001 From: John Arnfield Date: Wed, 17 Aug 2011 20:15:47 +0100 Subject: [PATCH 4/5] Commas help too :) --- mongoengine/queryset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mongoengine/queryset.py b/mongoengine/queryset.py index a715b57d..93b4deca 100644 --- a/mongoengine/queryset.py +++ b/mongoengine/queryset.py @@ -617,7 +617,7 @@ class QuerySet(object): """ 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'] + geo_operators = ['within_distance', 'within_spherical_distance', 'within_box', 'within_polygon', 'near', 'near_sphere'] match_operators = ['contains', 'icontains', 'startswith', 'istartswith', 'endswith', 'iendswith', 'exact', 'iexact'] From b037fb3e21e7b9f4c535fe57b231caf692d0c762 Mon Sep 17 00:00:00 2001 From: John Arnfield Date: Wed, 17 Aug 2011 21:23:40 +0100 Subject: [PATCH 5/5] Added version check to the polygon test to ensure server version >= 1.9 --- tests/queryset.py | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/tests/queryset.py b/tests/queryset.py index 001d10be..5b0e658f 100644 --- a/tests/queryset.py +++ b/tests/queryset.py @@ -7,6 +7,7 @@ from mongoengine.queryset import (QuerySet, QuerySetManager, MultipleObjectsReturned, DoesNotExist, QueryFieldList) from mongoengine import * +from mongoengine.connection import _get_connection from mongoengine.tests import query_counter @@ -14,7 +15,7 @@ class QuerySetTest(unittest.TestCase): def setUp(self): connect(db='mongoenginetest') - + class Person(Document): name = StringField() age = IntField() @@ -2197,25 +2198,30 @@ class QuerySetTest(unittest.TestCase): self.assertEqual(events.count(), 1) self.assertEqual(events[0].id, event2.id) - # check that polygon works - polygon = [ - (41.912114,-87.694445), - (41.919395,-87.69084), - (41.927186,-87.681742), - (41.911731,-87.654276), - (41.898061,-87.656164), - ] - events = Event.objects(location__within_polygon=polygon) - self.assertEqual(events.count(), 1) - self.assertEqual(events[0].id, event1.id) - - polygon2 = [ - (54.033586,-1.742249), - (52.792797,-1.225891), - (53.389881,-4.40094) - ] - events = Event.objects(location__within_polygon=polygon2) - self.assertEqual(events.count(), 0) + # check that polygon works for users who have a server >= 1.9 + server_version = tuple( + _get_connection().server_info()['version'].split('.') + ) + required_version = tuple("1.9.0".split(".")) + if server_version >= required_version: + polygon = [ + (41.912114,-87.694445), + (41.919395,-87.69084), + (41.927186,-87.681742), + (41.911731,-87.654276), + (41.898061,-87.656164), + ] + events = Event.objects(location__within_polygon=polygon) + self.assertEqual(events.count(), 1) + self.assertEqual(events[0].id, event1.id) + + polygon2 = [ + (54.033586,-1.742249), + (52.792797,-1.225891), + (53.389881,-4.40094) + ] + events = Event.objects(location__within_polygon=polygon2) + self.assertEqual(events.count(), 0) Event.drop_collection()