def test_union(self): """Union with all combinations of geometries/geometry fields.""" geom = Point(-95.363151, 29.763374, srid=4326) union = ( City.objects.annotate(union=functions.Union("point", geom)) .get(name="Dallas") .union ) expected = fromstr( "MULTIPOINT(-96.801611 32.782057,-95.363151 29.763374)", srid=4326 ) self.assertTrue(expected.equals(union)) union = ( City.objects.annotate(union=functions.Union(geom, "point")) .get(name="Dallas") .union ) self.assertTrue(expected.equals(union)) union = ( City.objects.annotate(union=functions.Union("point", "point")) .get(name="Dallas") .union ) expected = GEOSGeometry("POINT(-96.801611 32.782057)", srid=4326) self.assertTrue(expected.equals(union)) union = ( City.objects.annotate(union=functions.Union(geom, geom)) .get(name="Dallas") .union ) self.assertTrue(geom.equals(union))
def test_geoagg_subquery(self): tx = Country.objects.get(name='Texas') union = GEOSGeometry('MULTIPOINT(-96.801611 32.782057,-95.363151 29.763374)') # Use distinct() to force the usage of a subquery for aggregation. with CaptureQueriesContext(connection) as ctx: self.assertIs(union.equals( City.objects.filter(point__within=tx.mpoly).distinct().aggregate( Union('point'), )['point__union'], ), True) self.assertIn('subquery', ctx.captured_queries[0]['sql'])
def test_geoagg_subquery(self): ks = State.objects.get(name='Kansas') union = GEOSGeometry('MULTIPOINT(-95.235060 38.971823)') # Use distinct() to force the usage of a subquery for aggregation. with CaptureQueriesContext(connection) as ctx: self.assertIs( union.equals( City.objects.filter( point__within=ks.poly).distinct().aggregate( Union('point'), )['point__union'], ), True) self.assertIn('subquery', ctx.captured_queries[0]['sql'])
def test14_collect(self): "Testing the `collect` GeoQuerySet method and `Collect` aggregate." # Reference query: # SELECT AsText(ST_Collect("relatedapp_location"."point")) FROM "relatedapp_city" LEFT OUTER JOIN # "relatedapp_location" ON ("relatedapp_city"."location_id" = "relatedapp_location"."id") # WHERE "relatedapp_city"."state" = 'TX'; ref_geom = GEOSGeometry('MULTIPOINT(-97.516111 33.058333,-96.801611 32.782057,-95.363151 29.763374,-96.801611 32.782057)') c1 = City.objects.filter(state='TX').collect(field_name='location__point') c2 = City.objects.filter(state='TX').aggregate(Collect('location__point'))['location__point__collect'] for coll in (c1, c2): # Even though Dallas and Ft. Worth share same point, Collect doesn't # consolidate -- that's why 4 points in MultiPoint. self.assertEqual(4, len(coll)) self.assertTrue(ref_geom.equals(coll))
def test_union(self): """Union with all combinations of geometries/geometry fields.""" geom = Point(-95.363151, 29.763374, srid=4326) union = City.objects.annotate(union=functions.Union('point', geom)).get(name='Dallas').union expected = fromstr('MULTIPOINT(-96.801611 32.782057,-95.363151 29.763374)', srid=4326) self.assertTrue(expected.equals(union)) union = City.objects.annotate(union=functions.Union(geom, 'point')).get(name='Dallas').union self.assertTrue(expected.equals(union)) union = City.objects.annotate(union=functions.Union('point', 'point')).get(name='Dallas').union expected = GEOSGeometry('POINT(-96.801611 32.782057)', srid=4326) self.assertTrue(expected.equals(union)) union = City.objects.annotate(union=functions.Union(geom, geom)).get(name='Dallas').union self.assertTrue(geom.equals(union))
def test_collect(self): """ Testing the `Collect` aggregate. """ # Reference query: # SELECT AsText(ST_Collect("relatedapp_location"."point")) FROM "relatedapp_city" LEFT OUTER JOIN # "relatedapp_location" ON ("relatedapp_city"."location_id" = "relatedapp_location"."id") # WHERE "relatedapp_city"."state" = 'TX'; ref_geom = GEOSGeometry( 'MULTIPOINT(-97.516111 33.058333,-96.801611 32.782057,' '-95.363151 29.763374,-96.801611 32.782057)' ) coll = City.objects.filter(state='TX').aggregate(Collect('location__point'))['location__point__collect'] # Even though Dallas and Ft. Worth share same point, Collect doesn't # consolidate -- that's why 4 points in MultiPoint. self.assertEqual(4, len(coll)) self.assertTrue(ref_geom.equals(coll))
def test_unionagg_tolerance(self): City.objects.create( point=fromstr('POINT(-96.467222 32.751389)', srid=4326), name='Forney', ) tx = Country.objects.get(name='Texas').mpoly # Tolerance is greater than distance between Forney and Dallas, that's # why Dallas is ignored. forney_houston = GEOSGeometry( 'MULTIPOINT(-95.363151 29.763374, -96.467222 32.751389)', srid=4326, ) self.assertIs( forney_houston.equals( City.objects.filter(point__within=tx).aggregate( Union('point', tolerance=32000), )['point__union'], ), True, )
def test_unionagg(self): """ Testing the `Union` aggregate. """ tx = Country.objects.get(name='Texas').mpoly # Houston, Dallas -- Ordering may differ depending on backend or GEOS version. union = GEOSGeometry('MULTIPOINT(-96.801611 32.782057,-95.363151 29.763374)') qs = City.objects.filter(point__within=tx) with self.assertRaises(ValueError): qs.aggregate(Union('name')) # Using `field_name` keyword argument in one query and specifying an # order in the other (which should not be used because this is # an aggregate method on a spatial column) u1 = qs.aggregate(Union('point'))['point__union'] u2 = qs.order_by('name').aggregate(Union('point'))['point__union'] self.assertTrue(union.equals(u1)) self.assertTrue(union.equals(u2)) qs = City.objects.filter(name='NotACity') self.assertIsNone(qs.aggregate(Union('point'))['point__union'])