From 51102c933076273d22a3cfd2cc1e78f68d1c3031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Mercader?= Date: Fri, 18 Mar 2011 12:05:16 +0000 Subject: [PATCH] Add spatial search based on PostGIS for packages with geographic extent --- ckanext/harvest/__init__.py | 6 ++- ckanext/harvest/controllers/api.py | 80 ++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 ckanext/harvest/controllers/api.py diff --git a/ckanext/harvest/__init__.py b/ckanext/harvest/__init__.py index 37586ff..ad6f363 100644 --- a/ckanext/harvest/__init__.py +++ b/ckanext/harvest/__init__.py @@ -66,7 +66,11 @@ class Harvest(SingletonPlugin): map.connect('harvest_create', '/harvest/:id/refresh', controller='ckanext.harvest.controllers.view:ViewController', action='create_harvesting_job') - + + map.connect('api_spatial_query', '/api/2/search/package/geo', + controller='ckanext.harvest.controllers.api:ApiController', + action='spatial_query') + return map def update_config(self, config): diff --git a/ckanext/harvest/controllers/api.py b/ckanext/harvest/controllers/api.py new file mode 100644 index 0000000..cee5b73 --- /dev/null +++ b/ckanext/harvest/controllers/api.py @@ -0,0 +1,80 @@ +from ckan.lib.helpers import json +import ckan.lib.helpers as h +from ckan.lib.base import c, g, request, \ + response, session, render, config, abort, redirect +from ckan.controllers.rest import BaseApiController + + +from ckan.model import Session + + +class ApiController(BaseApiController): + def _get_srid(self,crs): + """Returns the SRID for the provided CRS definition + The CRS can be defined in the following formats + - urn:ogc:def:crs:EPSG::4258 + - EPSG:4258 + - 4258 + """ + + if ':' in crs: + crs = crs.split(':') + srid = crs[len(crs)-1] + else: + srid = crs + + return int(srid) + + + def spatial_query(self): + if not 'bbox' in request.params: + abort(400) + + bbox = request.params['bbox'].split(',') + if len(bbox) is not 4: + abort(400) + + minx = float(bbox[0]) + miny = float(bbox[1]) + maxx = float(bbox[2]) + maxy = float(bbox[3]) + + params = {'minx':minx,'miny':miny,'maxx':maxx,'maxy':maxy} + + if 'crs' in request.params: + # The input bounding box is defined in another projection, we need + # to transform it + srid = self._get_srid(request.params['crs']) + + statement = """SELECT package_id FROM package_extent WHERE + ST_Intersects( + ST_Transform( + ST_GeomFromText('POLYGON ((%(minx)s %(miny)s, + %(maxx)s %(miny)s, + %(maxx)s %(maxy)s, + %(minx)s %(maxy)s, + %(minx)s %(miny)s))',%(srid)s), + 4258) + ,the_geom)""" + params.update({'srid': srid}) + else: + statement = """SELECT package_id FROM package_extent WHERE + ST_Intersects( + ST_GeomFromText('POLYGON ((%(minx)s %(miny)s, + %(maxx)s %(miny)s, + %(maxx)s %(maxy)s, + %(minx)s %(maxy)s, + %(minx)s %(miny)s))',4258), + the_geom)""" + try: + conn = Session.connection() + rows = conn.execute(statement,params) + ids = [row['package_id'] for row in rows] + + output = dict(count=len(ids),results=ids) + + return self._finish_ok(output) + except: + abort(500) + +