diff --git a/python/dbapi/api/raw.py b/python/dbapi/api/raw.py index 35c43ffd..bcaaff9e 100644 --- a/python/dbapi/api/raw.py +++ b/python/dbapi/api/raw.py @@ -19,7 +19,26 @@ from .db import UnderpassDB -RESULTS_PER_PAGE = 25 +RESULTS_PER_PAGE = 100 + +# TODO: improve this code +def tagsQueryFilter(tagsQuery, table): + query = "" + tags = tagsQuery.split(",") + keyValue = tags[0].split("=") + + if len(keyValue) == 2: + query += "{0}.tags->'{1}' ~* '^{2}'".format(table, keyValue[0], keyValue[1]) + else: + query += "{0}.tags ? '{1}'".format(table, keyValue[0]) + + for tag in tags[1:]: + keyValue = tag.split("=") + if len(keyValue) == 2: + query += "OR {0}.tags->'{!}' ~* '^{2}'".format(table, keyValue[0], keyValue[1]) + else: + query += "OR {0}.tags ? '{1}'".format(table, keyValue[0]) + return query class Raw: def __init__(self, db): @@ -28,8 +47,7 @@ def __init__(self, db): def getPolygons( self, area = None, - key = None, - value = None, + tags = None, hashtag = None, responseType = "json", page = None @@ -38,7 +56,7 @@ def getPolygons( SELECT 'Polygon' as type, ways_poly.osm_id as id, ways_poly.timestamp, geom as geometry, tags, status FROM ways_poly \ LEFT JOIN validation ON validation.osm_id = ways_poly.osm_id \ WHERE \ - {0} {1} {2} {3} \ + {0} {1} {2} \ ), \ t_features AS ( \ SELECT jsonb_build_object( 'type', 'Feature', 'id', id, 'properties', to_jsonb(t_ways) \ @@ -46,17 +64,15 @@ def getPolygons( ) SELECT jsonb_build_object( 'type', 'FeatureCollection', 'features', jsonb_agg(t_features.feature) ) \ as result FROM t_features;".format( "ST_Intersects(\"geom\", ST_GeomFromText('POLYGON(({0}))', 4326) )".format(area) if area else "1=1 ", - "and ways_poly.tags ? '{0}'".format(key) if key and not value else "", - "and ways_poly.tags->'{0}' ~* '^{1}'".format(key, value) if key and value else "", - "ORDER BY ways_poly.timestamp DESC LIMIT " + str(RESULTS_PER_PAGE) + " OFFSET {0}".format(page * RESULTS_PER_PAGE) if page else "", + "AND (" + tagsQueryFilter(tags, "ways_poly") + ")" if tags else "", + "ORDER BY ways_poly.timestamp DESC LIMIT " + str(RESULTS_PER_PAGE), ) return self.underpassDB.run(query, responseType, True) def getLines( self, area = None, - key = None, - value = None, + tags = None, hashtag = None, responseType = "json", page = None @@ -65,7 +81,7 @@ def getLines( SELECT 'LineString' as type, ways_line.osm_id as id, ways_line.timestamp, geom as geometry, tags, status FROM ways_line \ LEFT JOIN validation ON validation.osm_id = ways_line.osm_id \ WHERE \ - {0} {1} {2} {3} \ + {0} {1} {2} \ ), \ t_features AS ( \ SELECT jsonb_build_object( 'type', 'Feature', 'id', id, 'properties', to_jsonb(t_ways) \ @@ -73,17 +89,15 @@ def getLines( ) SELECT jsonb_build_object( 'type', 'FeatureCollection', 'features', jsonb_agg(t_features.feature) ) \ as result FROM t_features;".format( "ST_Intersects(\"geom\", ST_GeomFromText('POLYGON(({0}))', 4326) )".format(area) if area else "1=1 ", - "and ways_line.tags ? '{0}'".format(key) if key and not value else "", - "and ways_line.tags->'{0}' ~* '^{1}'".format(key, value) if key and value else "", - "ORDER BY ways_line.timestamp DESC LIMIT " + str(RESULTS_PER_PAGE) + " OFFSET {0}".format(page * RESULTS_PER_PAGE) if page else "", + "AND (" + tagsQueryFilter(tags, "ways_line") + ")" if tags else "", + "ORDER BY ways_line.timestamp DESC LIMIT " + str(RESULTS_PER_PAGE), ) return self.underpassDB.run(query, responseType, True) def getNodes( self, area = None, - key = None, - value = None, + tags = None, hashtag = None, responseType = "json", page = None @@ -92,7 +106,7 @@ def getNodes( SELECT 'Point' as type, nodes.osm_id as id, nodes.timestamp, geom as geometry, tags, status FROM nodes \ LEFT JOIN validation ON validation.osm_id = nodes.osm_id \ WHERE \ - {0} {1} {2} {3} \ + {0} {1} {2} \ ), \ t_features AS ( \ SELECT jsonb_build_object( 'type', 'Feature', 'id', id, 'properties', to_jsonb(t_nodes) \ @@ -100,17 +114,15 @@ def getNodes( ) SELECT jsonb_build_object( 'type', 'FeatureCollection', 'features', jsonb_agg(t_features.feature) ) \ as result FROM t_features;".format( "ST_Intersects(\"geom\", ST_GeomFromText('POLYGON(({0}))', 4326) )".format(area) if area else "1=1 ", - "and nodes.tags ? '{0}'".format(key) if key and not value else "", - "and nodes.tags->'{0}' ~* '^{1}'".format(key, value) if key and value else "", - "ORDER BY nodes.timestamp DESC LIMIT " + str(RESULTS_PER_PAGE) + " OFFSET {0}".format(page * RESULTS_PER_PAGE) if page else "", + "AND (" + tagsQueryFilter(tags, "nodes") + ")" if tags else "", + "ORDER BY nodes.timestamp DESC LIMIT " + str(RESULTS_PER_PAGE), ) return self.underpassDB.run(query, responseType, True) def getAll( self, area = None, - key = None, - value = None, + tags = None, hashtag = None, responseType = "json", page = None @@ -118,37 +130,34 @@ def getAll( polygons = self.getPolygons( area, - key, - value, + tags, hashtag, responseType, page) lines = self.getLines( area, - key, - value, + tags, hashtag, responseType, page) nodes = self.getNodes( area, - key, - value, + tags, hashtag, responseType, page) result = {'type': 'FeatureCollection', 'features': []} - if polygons['features']: + if 'features' in polygons and polygons['features']: result['features'] = result['features'] + polygons['features'] - if lines['features']: + if 'features' in lines and lines['features']: result['features'] = result['features'] + lines['features'] - elif nodes['features']: + elif 'features' in nodes and nodes['features']: result['features'] = result['features'] + nodes['features'] return result @@ -156,35 +165,30 @@ def getAll( def getPolygonsList( self, area = None, - key = None, - value = None, + tags = None, hashtag = None, responseType = "json", page = None ): - if page == 0: - page = 1 query = "with t_ways AS ( \ SELECT 'way' as type, 'Polygon' as geotype, ways_poly.osm_id as id, ST_X(ST_Centroid(geom)) as lat, ST_Y(ST_Centroid(geom)) as lon, ways_poly.timestamp, tags, status FROM ways_poly \ LEFT JOIN validation ON validation.osm_id = ways_poly.osm_id \ WHERE \ - {0} {1} {2} {3} \ + {0} {1} {2} \ ), t_features AS ( \ SELECT to_jsonb(t_ways) as feature from t_ways \ ) SELECT jsonb_agg(t_features.feature) as result FROM t_features;".format( "ST_Intersects(\"geom\", ST_GeomFromText('POLYGON(({0}))', 4326) )".format(area) if area else "1=1 ", - "and ways_poly.tags ? '{0}'".format(key) if key and not value else "", - "and ways_poly.tags->'{0}' ~* '^{1}'".format(key, value) if key and value else "", - "ORDER BY ways_poly.timestamp DESC LIMIT " + str(RESULTS_PER_PAGE) + " OFFSET {0}".format(page * RESULTS_PER_PAGE) if page else "", + "AND (" + tagsQueryFilter(tags, "ways_poly") + ")" if tags else "", + "ORDER BY ways_poly.timestamp DESC LIMIT " + str(RESULTS_PER_PAGE), ) return self.underpassDB.run(query, responseType, True) def getLinesList( self, area = None, - key = None, - value = None, + tags = None, hashtag = None, responseType = "json", page = None @@ -196,13 +200,12 @@ def getLinesList( SELECT 'way' as type, 'LineString' as geotype, ways_line.osm_id as id, ST_X(ST_Centroid(geom)) as lat, ST_Y(ST_Centroid(geom)) as lon, ways_line.timestamp, tags, status FROM ways_line \ LEFT JOIN validation ON validation.osm_id = ways_line.osm_id \ WHERE \ - {0} {1} {2} {3} \ + {0} {1} {2} \ ), t_features AS ( \ SELECT to_jsonb(t_lines) as feature from t_lines \ ) SELECT jsonb_agg(t_features.feature) as result FROM t_features;".format( "ST_Intersects(\"geom\", ST_GeomFromText('POLYGON(({0}))', 4326) )".format(area) if area else "1=1 ", - "and ways_line.tags ? '{0}'".format(key) if key and not value else "", - "and ways_line.tags->'{0}' ~* '^{1}'".format(key, value) if key and value else "", + "AND (" + tagsQueryFilter(tags, "ways_line") + ")" if tags else "", "ORDER BY ways_line.timestamp DESC LIMIT " + str(RESULTS_PER_PAGE) + " OFFSET {0}".format(page * RESULTS_PER_PAGE) if page else "", ) return self.underpassDB.run(query, responseType, True) @@ -210,8 +213,7 @@ def getLinesList( def getNodesList( self, area = None, - key = None, - value = None, + tags = None, hashtag = None, responseType = "json", page = None @@ -222,14 +224,13 @@ def getNodesList( query = "with t_nodes AS ( \ SELECT 'node' as type, 'Point' as geotype, nodes.osm_id as id, ST_X(ST_Centroid(geom)) as lat, ST_Y(ST_Centroid(geom)) as lon, nodes.timestamp, tags, status FROM nodes \ LEFT JOIN validation ON validation.osm_id = nodes.osm_id \ - WHERE {0} {1} {2} {3} \ + WHERE {0} {1} {2} \ ), \ t_features AS ( \ SELECT to_jsonb(t_nodes) AS feature FROM t_nodes \ ) SELECT jsonb_agg(t_features.feature) as result FROM t_features;".format( "ST_Intersects(\"geom\", ST_GeomFromText('POLYGON(({0}))', 4326) )".format(area) if area else "1=1 ", - "and nodes.tags ? '{0}'".format(key) if key and not value else "", - "and nodes.tags->'{0}' ~* '^{1}'".format(key, value) if key and value else "", + "AND (" + tagsQueryFilter(tags, "nodes") + ")" if tags else "", "ORDER BY nodes.timestamp DESC LIMIT " + str(RESULTS_PER_PAGE) + " OFFSET {0}".format(page * RESULTS_PER_PAGE) if page else "", ) return self.underpassDB.run(query, responseType, True) @@ -237,8 +238,7 @@ def getNodesList( def getAllList( self, area = None, - key = None, - value = None, + tags = None, hashtag = None, responseType = "json", page = None @@ -246,24 +246,21 @@ def getAllList( polygons = self.getPolygonsList( area, - key, - value, + tags, hashtag, responseType, page) lines = self.getLinesList( area, - key, - value, + tags, hashtag, responseType, page) nodes = self.getNodesList( area, - key, - value, + tags, hashtag, responseType, page) diff --git a/python/restapi/main.py b/python/restapi/main.py index 41d4d7ba..f9dd6446 100644 --- a/python/restapi/main.py +++ b/python/restapi/main.py @@ -63,7 +63,7 @@ allow_origins=origins, allow_credentials=True, allow_methods=["*"], - allow_headers=["*"], + allow_headers=["*"] ) db = UnderpassDB(config.UNDERPASS_DB) @@ -157,8 +157,7 @@ def osmchangeValidate(request: OsmchangeValidateRequest): def getPolygons(request: RawRequest): results = rawer.getPolygons( area = request.area or None, - key = request.key or "", - value = request.value or "", + tags = request.tags or "", page = request.page ) return results @@ -167,8 +166,7 @@ def getPolygons(request: RawRequest): def getNodes(request: RawRequest): results = rawer.getNodes( area = request.area, - key = request.key or "", - value = request.value or "", + tags = request.tags or "", page = request.page ) return results @@ -177,8 +175,7 @@ def getNodes(request: RawRequest): def getLines(request: RawRequest): results = rawer.getLines( area = request.area, - key = request.key or "", - value = request.value or "", + tags = request.tags or "", page = request.page ) return results @@ -187,8 +184,7 @@ def getLines(request: RawRequest): def getLines(request: RawRequest): results = rawer.getAll( area = request.area, - key = request.key or "", - value = request.value or "", + tags = request.tags or "", page = request.page ) return results @@ -197,8 +193,7 @@ def getLines(request: RawRequest): def getPolygonsList(request: RawRequest): results = rawer.getPolygonsList( area = request.area or None, - key = request.key or "", - value = request.value or "", + tags = request.tags or "", page = request.page ) return results @@ -207,8 +202,7 @@ def getPolygonsList(request: RawRequest): def getNodesList(request: RawRequest): results = rawer.getNodesList( area = request.area or None, - key = request.key or "", - value = request.value or "", + tags = request.tags or "", page = request.page ) return results @@ -217,8 +211,7 @@ def getNodesList(request: RawRequest): def getAllList(request: RawRequest): results = rawer.getAllList( area = request.area or None, - key = request.key or "", - value = request.value or "", - page = request.page + tags = request.tags or "", + page = request.page, ) - return results \ No newline at end of file + return results