From 111942e181fe442562a1e0cc3c9089ed3c1fc050 Mon Sep 17 00:00:00 2001 From: TaehoonK Date: Wed, 28 Feb 2024 14:06:46 +0000 Subject: [PATCH] Fix some minor bugs (typo of interpolation type, date-time format, name of the queryable resources) --- pygeoapi/api.py | 32 +++--- pygeoapi/flask_app.py | 19 ++-- pygeoapi/models/process_data.py | 192 ++++++++++++++++---------------- sql/initdb-mobilitydb.sh | 3 +- sql/mf-api.sql | 5 +- 5 files changed, 126 insertions(+), 125 deletions(-) diff --git a/pygeoapi/api.py b/pygeoapi/api.py index 2572d43..b3da7ca 100644 --- a/pygeoapi/api.py +++ b/pygeoapi/api.py @@ -866,13 +866,13 @@ def describe_collections(self, request: Union[APIRequest, Any]) -> Tuple[dict, i time = [] lifespan = row[2] if lifespan is not None: - time.append(lifespan._lower.strftime("%Y/%m/%dT%H:%M:%SZ")) - time.append(lifespan._upper.strftime("%Y/%m/%dT%H:%M:%SZ")) + time.append(lifespan._lower.strftime("%Y-%m-%dT%H:%M:%SZ")) + time.append(lifespan._upper.strftime("%Y-%m-%dT%H:%M:%SZ")) else: if extend_stbox is not None: if extend_stbox.tmin is not None: - time.append(extend_stbox.tmin.strftime("%Y/%m/%dT%H:%M:%SZ")) - time.append(extend_stbox.tmax.strftime("%Y/%m/%dT%H:%M:%SZ")) + time.append(extend_stbox.tmin.strftime("%Y-%m-%dT%H:%M:%SZ")) + time.append(extend_stbox.tmax.strftime("%Y-%m-%dT%H:%M:%SZ")) collection['extent'] = { 'spatial': { @@ -1064,13 +1064,13 @@ def get_collection(self, request: Union[APIRequest, Any], time = [] lifespan = row[2] if lifespan is not None: - time.append(lifespan._lower.strftime("%Y/%m/%dT%H:%M:%SZ")) - time.append(lifespan._upper.strftime("%Y/%m/%dT%H:%M:%SZ")) + time.append(lifespan._lower.strftime("%Y-%m-%dT%H:%M:%SZ")) + time.append(lifespan._upper.strftime("%Y-%m-%dT%H:%M:%SZ")) else: if extend_stbox is not None: if extend_stbox.tmin is not None: - time.append(extend_stbox.tmin.strftime("%Y/%m/%dT%H:%M:%SZ")) - time.append(extend_stbox.tmax.strftime("%Y/%m/%dT%H:%M:%SZ")) + time.append(extend_stbox.tmin.strftime("%Y-%m-%dT%H:%M:%SZ")) + time.append(extend_stbox.tmax.strftime("%Y-%m-%dT%H:%M:%SZ")) collection['extent'] = { 'spatial': { @@ -1282,13 +1282,13 @@ def get_collection_items( time = [] lifespan = row[4] if lifespan is not None: - time.append(lifespan._lower.strftime("%Y/%m/%dT%H:%M:%SZ")) - time.append(lifespan._upper.strftime("%Y/%m/%dT%H:%M:%SZ")) + time.append(lifespan._lower.strftime("%Y-%m-%dT%H:%M:%SZ")) + time.append(lifespan._upper.strftime("%Y-%m-%dT%H:%M:%SZ")) else: if extend_stbox is not None: if extend_stbox.tmin is not None: - time.append(extend_stbox.tmin.strftime("%Y/%m/%dT%H:%M:%SZ")) - time.append(extend_stbox.tmax.strftime("%Y/%m/%dT%H:%M:%SZ")) + time.append(extend_stbox.tmin.strftime("%Y-%m-%dT%H:%M:%SZ")) + time.append(extend_stbox.tmax.strftime("%Y-%m-%dT%H:%M:%SZ")) mfeature['time'] = time if 'crs' not in mfeature: @@ -1524,13 +1524,13 @@ def get_collection_item(self, request: Union[APIRequest, Any], time = [] lifespan = row[4] if lifespan is not None: - time.append(lifespan._lower.strftime("%Y/%m/%dT%H:%M:%SZ")) - time.append(lifespan._upper.strftime("%Y/%m/%dT%H:%M:%SZ")) + time.append(lifespan._lower.strftime("%Y-%m-%dT%H:%M:%SZ")) + time.append(lifespan._upper.strftime("%Y-%m-%dT%H:%M:%SZ")) else: if extend_stbox is not None: if extend_stbox.tmin is not None: - time.append(extend_stbox.tmin.strftime("%Y/%m/%dT%H:%M:%SZ")) - time.append(extend_stbox.tmax.strftime("%Y/%m/%dT%H:%M:%SZ")) + time.append(extend_stbox.tmin.strftime("%Y-%m-%dT%H:%M:%SZ")) + time.append(extend_stbox.tmax.strftime("%Y-%m-%dT%H:%M:%SZ")) mfeature['time'] = time if 'crs' not in mfeature: diff --git a/pygeoapi/flask_app.py b/pygeoapi/flask_app.py index 35bd75e..3cc636b 100644 --- a/pygeoapi/flask_app.py +++ b/pygeoapi/flask_app.py @@ -197,10 +197,8 @@ def collections(collection_id=None): api_.get_collection(request, collection_id)) -@BLUEPRINT.route('/collections//items', - methods=['GET', 'POST']) -@BLUEPRINT.route('/collections//items/', - methods=['GET', 'DELETE']) +@BLUEPRINT.route('/collections//items', methods=['GET', 'POST']) +@BLUEPRINT.route('/collections//items/', methods=['GET', 'DELETE']) def collection_items(collection_id, item_id=None): """ OGC API collections items endpoint @@ -216,13 +214,11 @@ def collection_items(collection_id, item_id=None): return get_response( api_.get_collection_items(request, collection_id)) elif request.method == 'POST': # filter or manage items - return get_response(api_.manage_collection_item(request, 'create', - collection_id)) + return get_response(api_.manage_collection_item(request, 'create', collection_id)) elif request.method == 'DELETE': return get_response( - api_.manage_collection_item(request, 'delete', - collection_id, item_id)) + api_.manage_collection_item(request, 'delete', collection_id, item_id)) else: return get_response( api_.get_collection_item(request, collection_id, item_id)) @@ -247,13 +243,12 @@ def collection_items_tgeometries(collection_id, item_id, tGeometry_id=None): return get_response( api_.get_collection_items_tGeometry(request, collection_id, item_id)) elif request.method == 'POST': # filter or manage items - return get_response(api_.manage_collection_item_tGeometry(request, 'create', - collection_id, item_id)) + return get_response( + api_.manage_collection_item_tGeometry(request, 'create',collection_id, item_id)) elif request.method == 'DELETE': return get_response( - api_.manage_collection_item_tGeometry(request, 'delete', - collection_id, item_id, tGeometry_id)) + api_.manage_collection_item_tGeometry(request, 'delete', collection_id, item_id, tGeometry_id)) @BLUEPRINT.route('/collections//items//tgsequence//velocity', diff --git a/pygeoapi/models/process_data.py b/pygeoapi/models/process_data.py index 67a389c..6c8a14a 100644 --- a/pygeoapi/models/process_data.py +++ b/pygeoapi/models/process_data.py @@ -117,14 +117,17 @@ def getFeatures(self, collection_id, bbox='', datetime='', limit=10, offset=0, s select_query += "from (select mfeature.collection_id, mfeature.mfeature_id, mfeature.mf_geometry, mfeature.mf_property, mfeature.lifespan, extent(tgeometry.tgeometry_property) as extentTGeometry " select_query += "from mfeature " select_query += "left outer join tgeometry on mfeature.collection_id = tgeometry.collection_id and mfeature.mfeature_id = tgeometry.mfeature_id " - select_query += "where mfeature.collection_id ='{0}' ".format(collection_id) + select_query += ("where mfeature.collection_id ='{0}' " + .format(collection_id)) select_query += "group by mfeature.collection_id, mfeature.mfeature_id, mfeature.mf_geometry, mfeature.mf_property, mfeature.lifespan) mfeature " select_query += "left outer join (select mfeature.collection_id, mfeature.mfeature_id, extent(tproperties.pvalue_float) as extentTPropertiesValueFloat, extent(tproperties.pvalue_text) as extentTPropertiesValueText " select_query += "from mfeature " select_query += "left outer join tproperties on mfeature.collection_id = tproperties.collection_id and mfeature.mfeature_id = tproperties.mfeature_id " - select_query += "where mfeature.collection_id ='{0}' ".format(collection_id) + select_query += ("where mfeature.collection_id ='{0}' " + .format(collection_id)) select_query += "group by mfeature.collection_id, mfeature.mfeature_id) tproperties ON mfeature.collection_id = tproperties.collection_id and mfeature.mfeature_id = tproperties.mfeature_id " - select_query += "where 1=1 {0} {1}".format(bbox_restriction, datetime_restriction) + select_query += ("where 1=1 {0} {1}" + .format(bbox_restriction, datetime_restriction)) cursor.execute(select_query) rows = cursor.fetchall() @@ -142,14 +145,16 @@ def getFeatures(self, collection_id, bbox='', datetime='', limit=10, offset=0, s select_geometry_query += "from (select mfeature.collection_id, mfeature.mfeature_id, mfeature.mf_geometry, mfeature.mf_property, mfeature.lifespan, extent(tgeometry.tgeometry_property) as extentTGeometry " select_geometry_query += "from mfeature " select_geometry_query += "left outer join tgeometry on mfeature.collection_id = tgeometry.collection_id and mfeature.mfeature_id = tgeometry.mfeature_id " - select_geometry_query += "where mfeature.collection_id ='{0}' ".format(collection_id) + select_geometry_query += ("where mfeature.collection_id ='{0}' " + .format(collection_id)) select_geometry_query += "group by mfeature.collection_id, mfeature.mfeature_id, mfeature.mf_geometry, mfeature.mf_property, mfeature.lifespan) mfeature " - select_geometry_query += "where 1=1 {0} {1}) mfeature ".format(bbox_restriction, limit_restriction) - select_geometry_query += "left outer join (select tgeometry.collection_id, tgeometry.mfeature_id, tgeometry.tgeometry_id, {0} as tgeometry_property ".format( - subTrajectory_field) + select_geometry_query += ("where 1=1 {0} {1}) mfeature " + .format(bbox_restriction, limit_restriction)) + select_geometry_query += ("left outer join (select tgeometry.collection_id, tgeometry.mfeature_id, tgeometry.tgeometry_id, {0} as tgeometry_property " + .format(subTrajectory_field)) select_geometry_query += "from tgeometry " - select_geometry_query += "where tgeometry.collection_id ='{0}' and {1} is not null".format(collection_id, - subTrajectory_field) + select_geometry_query += ("where tgeometry.collection_id ='{0}' and {1} is not null" + .format(collection_id, subTrajectory_field)) select_geometry_query += ") tgeometry ON mfeature.collection_id = tgeometry.collection_id and mfeature.mfeature_id = tgeometry.mfeature_id " select_geometry_query += "where 1=1 " @@ -163,16 +168,15 @@ def getFeature(self, collection_id, mfeature_id): select_query += "from (select mfeature.collection_id, mfeature.mfeature_id, mfeature.mf_geometry, mfeature.mf_property, mfeature.lifespan, extent(tgeometry.tgeometry_property) as extentTGeometry " select_query += "from mfeature " select_query += "left outer join tgeometry on mfeature.collection_id = tgeometry.collection_id and mfeature.mfeature_id = tgeometry.mfeature_id " - select_query += "where mfeature.collection_id ='{0}' AND mfeature.mfeature_id='{1}' ".format(collection_id, - mfeature_id) + select_query += ("where mfeature.collection_id ='{0}' AND mfeature.mfeature_id='{1}' " + .format(collection_id, mfeature_id)) select_query += "group by mfeature.collection_id, mfeature.mfeature_id, mfeature.mf_geometry, mfeature.mf_property, mfeature.lifespan) mfeature " cursor.execute(select_query) rows = cursor.fetchall() return rows - def getTemporalGeometries(self, collection_id, mfeature_id, bbox='', leaf='', datetime='', limit=10, offset=0, - subTrajectory=False): + def getTemporalGeometries(self, collection_id, mfeature_id, bbox='', leaf='', datetime='', limit=10, offset=0, subTrajectory=False): cursor = self.connection.cursor() tgeometry_property = 'null' @@ -183,6 +187,7 @@ def getTemporalGeometries(self, collection_id, mfeature_id, bbox='', leaf='', da bbox_restriction = " and box2d(stbox(" + s_bbox + ")) &&& box2d(stbox(tgeometry_property))" elif len(bbox) == 6: bbox_restriction = " and box3d(stbox_z(" + s_bbox + ")) &&& box3d(stbox(tgeometry_property))" + datetime_restriction = "" if datetime != '' and datetime is not None: datetime_restriction = " and atperiod(tgeometry_property, '[" + datetime + "]') is not null " @@ -192,12 +197,10 @@ def getTemporalGeometries(self, collection_id, mfeature_id, bbox='', leaf='', da elif subTrajectory == True or subTrajectory == "true": tgeometry_property = "atperiod(tgeometry_property, '[" + datetime + "]')" - select_query = "SELECT collection_id,mfeature_id,tgeometry_id, tgeometry_property, {0} ".format( - tgeometry_property) - select_query += "FROM tgeometry WHERE collection_id ='{0}' AND mfeature_id='{1}' {2} {3}".format(collection_id, - mfeature_id, - bbox_restriction, - datetime_restriction) + select_query = ("SELECT collection_id, mfeature_id, tgeometry_id, tgeometry_property, {0} " + .format(tgeometry_property)) + select_query += ("FROM tgeometry WHERE collection_id ='{0}' AND mfeature_id='{1}' {2} {3}" + .format(collection_id, mfeature_id, bbox_restriction, datetime_restriction)) cursor.execute(select_query) rows = cursor.fetchall() @@ -206,11 +209,11 @@ def getTemporalGeometries(self, collection_id, mfeature_id, bbox='', leaf='', da select_query += " LIMIT " + str(limit) + " OFFSET " + str(offset) cursor.execute(select_query) rows = cursor.fetchall() - numberReturned = len(rows); + numberReturned = len(rows) + return rows, numberMatched, numberReturned - def getTemporalProperties(self, collection_id, mfeature_id, datetime='', limit=10, offset=0, - subTemporalValue=False): + def getTemporalProperties(self, collection_id, mfeature_id, datetime='', limit=10, offset=0, subTemporalValue=False): cursor = self.connection.cursor() datetime_restriction = '' @@ -222,8 +225,8 @@ def getTemporalProperties(self, collection_id, mfeature_id, datetime='', limit=1 select_query = "select distinct on (tproperties.collection_id, tproperties.mfeature_id, tproperties.tproperties_name) " select_query += "tproperties.collection_id, tproperties.mfeature_id, tproperties.tproperties_name, tproperties.tproperty " select_query += "from tproperties " - select_query += "WHERE tproperties.collection_id ='{0}' AND tproperties.mfeature_id='{1}' {2}".format( - collection_id, mfeature_id, datetime_restriction) + select_query += ("WHERE tproperties.collection_id ='{0}' AND tproperties.mfeature_id='{1}' {2}" + .format(collection_id, mfeature_id, datetime_restriction)) cursor.execute(select_query) rows = cursor.fetchall() @@ -241,26 +244,25 @@ def getTemporalProperties(self, collection_id, mfeature_id, datetime='', limit=1 select_temporalValue_query = "select tproperties.collection_id, tproperties.mfeature_id, tproperties.tproperties_name, tproperties.tproperty, datetime_group, pvalue_float, pvalue_text " select_temporalValue_query += "from (select distinct on (tproperties.collection_id, tproperties.mfeature_id, tproperties.tproperties_name) " select_temporalValue_query += "tproperties.collection_id, tproperties.mfeature_id, tproperties.tproperties_name, tproperties.tproperty " - select_temporalValue_query += "from tproperties where tproperties.collection_id ='{0}' AND tproperties.mfeature_id='{1}' {2} {3}) tproperties ".format( - collection_id, mfeature_id, datetime_restriction, limit_restriction) + select_temporalValue_query += ("from tproperties where tproperties.collection_id ='{0}' AND tproperties.mfeature_id='{1}' {2} {3}) tproperties " + .format(collection_id, mfeature_id, datetime_restriction, limit_restriction)) select_temporalValue_query += "left outer join (select tproperties.collection_id, tproperties.mfeature_id, tproperties.tproperties_name, tproperties.datetime_group, " - select_temporalValue_query += "{0} as pvalue_float, {1} as pvalue_text ".format( - subTemporalValue_float_field, subTemporalValue_text_field) - select_temporalValue_query += "from tproperties where tproperties.collection_id ='{0}' AND tproperties.mfeature_id='{1}' ".format( - collection_id, mfeature_id) - select_temporalValue_query += "and ({0} is not null or {1} is not null)".format( - subTemporalValue_float_field, subTemporalValue_text_field) + select_temporalValue_query += ("{0} as pvalue_float, {1} as pvalue_text " + .format(subTemporalValue_float_field, subTemporalValue_text_field)) + select_temporalValue_query += ("from tproperties where tproperties.collection_id ='{0}' AND tproperties.mfeature_id='{1}' " + .format(collection_id, mfeature_id)) + select_temporalValue_query += ("and ({0} is not null or {1} is not null)" + .format(subTemporalValue_float_field, subTemporalValue_text_field)) select_temporalValue_query += ") tpropertiesvalue on tproperties.collection_id = tpropertiesvalue.collection_id " select_temporalValue_query += "and tproperties.mfeature_id = tpropertiesvalue.mfeature_id and tproperties.tproperties_name = tpropertiesvalue.tproperties_name " select_temporalValue_query += "where 1=1 order by datetime_group" - click.echo(select_temporalValue_query) + # click.echo(select_temporalValue_query) cursor.execute(select_temporalValue_query) rows = cursor.fetchall() return rows, numberMatched, numberReturned - def getTemporalPropertiesValue(self, collection_id, mfeature_id, tProperty_name, leaf='', datetime='', - subTemporalValue=False): + def getTemporalPropertiesValue(self, collection_id, mfeature_id, tProperty_name, leaf='', datetime='', subTemporalValue=False): cursor = self.connection.cursor() datetime_restriction = "" @@ -279,12 +281,12 @@ def getTemporalPropertiesValue(self, collection_id, mfeature_id, tProperty_name, select_query = "select tproperties.collection_id, tproperties.mfeature_id, tproperties.tproperties_name, tproperties.tproperty, datetime_group, pvalue_float, pvalue_text " select_query += "from (select distinct on (tproperties.collection_id, tproperties.mfeature_id, tproperties.tproperties_name) " select_query += "tproperties.collection_id, tproperties.mfeature_id, tproperties.tproperties_name, tproperties.tproperty " - select_query += "from tproperties where tproperties.collection_id ='{0}' AND tproperties.mfeature_id='{1}' AND tproperties.tproperties_name='{2}') tproperties ".format( - collection_id, mfeature_id, tProperty_name) + select_query += ("from tproperties where tproperties.collection_id ='{0}' AND tproperties.mfeature_id='{1}' AND tproperties.tproperties_name='{2}') tproperties " + .format(collection_id, mfeature_id, tProperty_name)) select_query += "left outer join (select tproperties.collection_id, tproperties.mfeature_id, tproperties.tproperties_name, tproperties.datetime_group, " select_query += "{0} as pvalue_float, {1} as pvalue_text ".format(float_field, text_field) - select_query += "from tproperties where tproperties.collection_id ='{0}' AND tproperties.mfeature_id='{1}' AND tproperties.tproperties_name='{2}' {3}".format( - collection_id, mfeature_id, tProperty_name, datetime_restriction) + select_query += ("from tproperties where tproperties.collection_id ='{0}' AND tproperties.mfeature_id='{1}' AND tproperties.tproperties_name='{2}' {3}" + .format(collection_id, mfeature_id, tProperty_name, datetime_restriction)) select_query += ") tpropertiesvalue on tproperties.collection_id = tpropertiesvalue.collection_id " select_query += "and tproperties.mfeature_id = tpropertiesvalue.mfeature_id and tproperties.tproperties_name = tpropertiesvalue.tproperties_name " select_query += "where 1=1 order by datetime_group" @@ -295,8 +297,8 @@ def getTemporalPropertiesValue(self, collection_id, mfeature_id, tProperty_name, def postCollection(self, collection_property): cursor = self.connection.cursor() - cursor.execute("INSERT INTO collection(collection_property) VALUES ('{0}') RETURNING collection_id".format( - json.dumps(collection_property))) + cursor.execute("INSERT INTO collection(collection_property) VALUES ('{0}') RETURNING collection_id" + .format(json.dumps(collection_property))) collection_id = cursor.fetchone()[0] return collection_id @@ -315,24 +317,22 @@ def postMovingFeature(self, collection_id, movingfeature): if 'geometry' in g_movingfeature: geometry = g_movingfeature.pop("geometry", None) cursor.execute( - "INSERT INTO mfeature(collection_id, mf_geometry, mf_property, lifespan) VALUES ('{0}', ST_GeomFromGeoJSON('{1}'), '{2}', {3}) RETURNING mfeature_id".format( - collection_id, json.dumps(geometry), json.dumps(g_movingfeature), lifespan)) + "INSERT INTO mfeature(collection_id, mf_geometry, mf_property, lifespan) VALUES ('{0}', ST_GeomFromGeoJSON('{1}'), '{2}', {3}) RETURNING mfeature_id" + .format(collection_id, json.dumps(geometry), json.dumps(g_movingfeature), lifespan)) else: cursor.execute( - "INSERT INTO mfeature(collection_id, mf_property, lifespan) VALUES ('{0}', '{1}', {2}) RETURNING mfeature_id".format( - collection_id, json.dumps(g_movingfeature), lifespan)) + "INSERT INTO mfeature(collection_id, mf_property, lifespan) VALUES ('{0}', '{1}', {2}) RETURNING mfeature_id" + .format(collection_id, json.dumps(g_movingfeature), lifespan)) mfeature_id = cursor.fetchone()[0] if temporalGeometries is not None: - temporalGeometries = [temporalGeometries] if not isinstance(temporalGeometries, - list) else temporalGeometries + temporalGeometries = [temporalGeometries] if not isinstance(temporalGeometries, list) else temporalGeometries for temporalGeometry in temporalGeometries: # for _ in range(10000): self.postTemporalGeometry(collection_id, mfeature_id, temporalGeometry) if temporalProperties is not None: - temporalProperties = [temporalProperties] if not isinstance(temporalProperties, - list) else temporalProperties + temporalProperties = [temporalProperties] if not isinstance(temporalProperties, list) else temporalProperties for temporalProperty in temporalProperties: self.postTemporalProperties(collection_id, mfeature_id, temporalProperty) @@ -347,8 +347,8 @@ def postTemporalGeometry(self, collection_id, mfeature_id, temporalGeometry): value = Temporal.from_mfjson(json.dumps(temporalGeometry)) cursor.execute( - "INSERT INTO tgeometry(collection_id, mfeature_id, tgeometry_property) VALUES ('{0}', '{1}', '{2}') RETURNING tgeometry_id".format( - collection_id, mfeature_id, str(value))) + "INSERT INTO tgeometry(collection_id, mfeature_id, tgeometry_property, tgeog_property) VALUES ('{0}', '{1}', '{2}', '{3}') RETURNING tgeometry_id" + .format(collection_id, mfeature_id, str(value), str(value))) tgeometry_id = cursor.fetchone()[0] return tgeometry_id @@ -375,20 +375,18 @@ def postTemporalProperties(self, collection_id, mfeature_id, temporalProperty): pymeos_initialize() value = Temporal.from_mfjson(json.dumps(temporalValue)) - insert_querry = "INSERT INTO tproperties(collection_id, mfeature_id, tproperties_name, datetime_group, tproperty, {0}) ".format( - pvalue_Column) - insert_querry += "VALUES ('{0}', '{1}', '{2}', {3}, '{4}', '{5}')".format(collection_id, mfeature_id, - tproperties_name, - datetime_group, json.dumps( - temporalProperty[tproperties_name]), str(value)) - cursor.execute(insert_querry) + insert_query = ("INSERT INTO tproperties(collection_id, mfeature_id, tproperties_name, datetime_group, tproperty, {0}) " + .format(pvalue_Column)) + insert_query += ("VALUES ('{0}', '{1}', '{2}', {3}, '{4}', '{5}')" + .format(collection_id, mfeature_id, tproperties_name, datetime_group, + json.dumps(temporalProperty[tproperties_name]), str(value))) + cursor.execute(insert_query) else: - insert_querry = "INSERT INTO tproperties(collection_id, mfeature_id, tproperties_name, datetime_group, tproperty) " - insert_querry += "VALUES ('{0}', '{1}', '{2}', {3}, '{4}')".format(collection_id, mfeature_id, - tproperties_name, datetime_group, - json.dumps(temporalProperty[ - tproperties_name])) - cursor.execute(insert_querry) + insert_query = "INSERT INTO tproperties(collection_id, mfeature_id, tproperties_name, datetime_group, tproperty) " + insert_query += ("VALUES ('{0}', '{1}', '{2}', {3}, '{4}')" + .format(collection_id, mfeature_id, tproperties_name, datetime_group, + json.dumps(temporalProperty[tproperties_name]))) + cursor.execute(insert_query) return tproperties_name @@ -409,10 +407,10 @@ def postTemporalValue(self, collection_id, mfeature_id, tproperties_name, tempor if dataType == 'MovingFloat': pvalue_Column = "pValue_float" - insert_querry = "INSERT INTO tproperties(collection_id, mfeature_id, tproperties_name, datetime_group, {0}) ".format( - pvalue_Column) - insert_querry += "VALUES ('{0}', '{1}', '{2}', {3}, '{4}')".format(collection_id, mfeature_id, tproperties_name, - datetime_group, str(value)) + insert_querry = ("INSERT INTO tproperties(collection_id, mfeature_id, tproperties_name, datetime_group, {0}) " + .format(pvalue_Column)) + insert_querry += ("VALUES ('{0}', '{1}', '{2}', {3}, '{4}')" + .format(collection_id, mfeature_id, tproperties_name, datetime_group, str(value))) cursor.execute(insert_querry) pValue_id = '' @@ -421,8 +419,8 @@ def postTemporalValue(self, collection_id, mfeature_id, tproperties_name, tempor def putCollection(self, collection_id, collection_property): cursor = self.connection.cursor() - cursor.execute("UPDATE collection set collection_property = '{0}' WHERE collection_id = '{1}'".format( - json.dumps(collection_property), collection_id)) + cursor.execute("UPDATE collection set collection_property = '{0}' WHERE collection_id = '{1}'" + .format(json.dumps(collection_property), collection_id)) def deleteCollection(self, restriction): cursor = self.connection.cursor() @@ -518,6 +516,8 @@ def createTemporalPropertyValue(self, datetimes, values, interpolation): def convertTemporalPropertyValueToBaseVersion(self, temporalPropertyValue): if 'interpolations' in temporalPropertyValue: temporalPropertyValue['interpolation'] = temporalPropertyValue['interpolations'][0] + if temporalPropertyValue['interpolation'] == 'Stepwise': + temporalPropertyValue['interpolation'] = 'Step' del temporalPropertyValue['interpolations'] if 'type' in temporalPropertyValue: @@ -569,8 +569,7 @@ def checkIfTemporalPropertyCanPost(self, collection_id, mfeature_id, temporalPro datetimes = g_temporalProperty["datetimes"] for i in range(len(datetimes)): if isinstance(datetimes[i], int): - datetimes[i] = datetime.datetime.fromtimestamp(datetimes[i] / 1e3).strftime( - "%Y/%m/%dT%H:%M:%S.%f") + datetimes[i] = datetime.datetime.fromtimestamp(datetimes[i] / 1e3).strftime("%Y/%m/%dT%H:%M:%S.%f") else: datetimes[i] = datetimes[i].replace('Z', '') @@ -583,10 +582,10 @@ def checkIfTemporalPropertyCanPost(self, collection_id, mfeature_id, temporalPro select_query = "select collection_id, mfeature_id, tproperties_name, count(datetime_group) as intersect_count " select_query += "from tproperties " - select_query += "where collection_id ='{0}' and mfeature_id='{1}' and tproperties_name in ({2}) ".format( - collection_id, mfeature_id, "'" + "', '".join(tproperties_name_list) + "'") - select_query += "and ((period(pvalue_float) && period(timestampset('{0}'))) or (period(pvalue_text) && period(timestampset('{0}')))) ".format( - "{" + ", ".join(datetimes) + "}") + select_query += ("where collection_id ='{0}' and mfeature_id='{1}' and tproperties_name in ({2}) " + .format(collection_id, mfeature_id, "'" + "', '".join(tproperties_name_list) + "'")) + select_query += ("and ((period(pvalue_float) && period(timestampset('{0}'))) or (period(pvalue_text) && period(timestampset('{0}')))) " + .format("{" + ", ".join(datetimes) + "}")) select_query += "group by collection_id, mfeature_id, tproperties_name" click.echo(select_query) cursor.execute(select_query) @@ -608,17 +607,20 @@ def getTemporalPropertiesGroup(self, collection_id, mfeature_id, datetimes): select_query = "select temp1.collection_id, temp1.mfeature_id, COALESCE(temp2.datetime_group, temp3.max_datetime_group) " select_query += "from (select collection_id, mfeature_id " select_query += "from tproperties " - select_query += "where collection_id ='{0}' and mfeature_id='{1}' ".format(collection_id, mfeature_id) + select_query += ("where collection_id ='{0}' and mfeature_id='{1}' " + .format(collection_id, mfeature_id)) select_query += ") temp1 " select_query += "left outer join (select collection_id, mfeature_id, datetime_group " select_query += "from tproperties " - select_query += "where collection_id ='{0}' and mfeature_id='{1}' ".format(collection_id, mfeature_id) - select_query += "and (timestampset_eq(timestampset(timestamps(pvalue_float)), timestampset('{0}')) or timestampset_eq(timestampset(timestamps(pvalue_text)), timestampset('{0}'))) ".format( - "{" + ", ".join(datetimes) + "}") + select_query += ("where collection_id ='{0}' and mfeature_id='{1}' " + .format(collection_id, mfeature_id)) + select_query += ("and (timestampset_eq(timestampset(timestamps(pvalue_float)), timestampset('{0}')) or timestampset_eq(timestampset(timestamps(pvalue_text)), timestampset('{0}'))) " + .format("{" + ", ".join(datetimes) + "}")) select_query += ") temp2 on temp1.collection_id = temp2.collection_id and temp1.mfeature_id = temp2.mfeature_id " select_query += "left outer join (select collection_id, mfeature_id, COALESCE(max(datetime_group), 0) + 1 as max_datetime_group " select_query += "from tproperties " - select_query += "where collection_id ='{0}' and mfeature_id='{1}' ".format(collection_id, mfeature_id) + select_query += ("where collection_id ='{0}' and mfeature_id='{1}' " + .format(collection_id, mfeature_id)) select_query += "group by collection_id, mfeature_id " select_query += ") temp3 on temp1.collection_id = temp3.collection_id and temp1.mfeature_id = temp3.mfeature_id " @@ -631,30 +633,30 @@ def getTemporalPropertiesGroup(self, collection_id, mfeature_id, datetimes): def get_velocity(self, collection_id, mfeature_id, tgeometry_id, datetime=None): form = "MTS" - key = "speed" + name = "velocity" cursor = self.connection.cursor() if datetime is None: - select_query = f"SELECT speed(tgeometry_property) AS speed FROM tgeometry WHERE collection_id = '{collection_id}' and mfeature_id = '{mfeature_id}' and tgeometry_id = '{tgeometry_id}'" + select_query = f"SELECT speed(tgeog_property) AS speed FROM tgeometry WHERE collection_id = '{collection_id}' and mfeature_id = '{mfeature_id}' and tgeometry_id = '{tgeometry_id}'" else: - select_query = f"SELECT valueAtTimestamp(speed(tgeometry_property), '{datetime}') AS speed, interpolation(speed(tgeometry_property)) AS interp FROM tgeometry WHERE collection_id = '{collection_id}' and mfeature_id = '{mfeature_id}' and tgeometry_id = '{tgeometry_id}'" + select_query = f"SELECT valueAtTimestamp(speed(tgeog_property), '{datetime}') AS speed, interpolation(speed(tgeog_property)) AS interp FROM tgeometry WHERE collection_id = '{collection_id}' and mfeature_id = '{mfeature_id}' and tgeometry_id = '{tgeometry_id}'" cursor.execute(select_query) rows = cursor.fetchall() - return self.to_tProperties(rows, key, form, datetime) + return self.to_tProperties(rows, name, form, datetime) def get_distance(self, collection_id, mfeature_id, tgeometry_id, datetime=None): form = "MTR" - key = "cumulativeLength" + name = "distance" cursor = self.connection.cursor() if datetime is None: - select_query = f"SELECT cumulativeLength(tgeometry_property) AS distance FROM tgeometry WHERE collection_id = '{collection_id}' and mfeature_id = '{mfeature_id}' and tgeometry_id = '{tgeometry_id}'" + select_query = f"SELECT cumulativeLength(tgeog_property) AS distance FROM tgeometry WHERE collection_id = '{collection_id}' and mfeature_id = '{mfeature_id}' and tgeometry_id = '{tgeometry_id}'" else: - select_query = f"SELECT valueAtTimestamp(cumulativeLength(tgeometry_property), '{datetime}') AS distance, interpolation(cumulativeLength(tgeometry_property)) AS interp FROM tgeometry WHERE collection_id = '{collection_id}' and mfeature_id = '{mfeature_id}' and tgeometry_id = '{tgeometry_id}'" + select_query = f"SELECT valueAtTimestamp(cumulativeLength(tgeog_property), '{datetime}') AS distance, interpolation(cumulativeLength(tgeog_property)) AS interp FROM tgeometry WHERE collection_id = '{collection_id}' and mfeature_id = '{mfeature_id}' and tgeometry_id = '{tgeometry_id}'" cursor.execute(select_query) rows = cursor.fetchall() - return self.to_tProperties(rows, key, form, datetime) + return self.to_tProperties(rows, name, form, datetime) def get_acceleration(self, collection_id, mfeature_id, tgeometry_id, datetime=None): @@ -666,7 +668,7 @@ def get_acceleration(self, collection_id, mfeature_id, tgeometry_id, datetime=No } cursor = self.connection.cursor() - select_query = f"SELECT speed(tgeometry_property) AS speed FROM tgeometry WHERE collection_id = '{collection_id}' and mfeature_id = '{mfeature_id}' and tgeometry_id = '{tgeometry_id}'" + select_query = f"SELECT speed(tgeog_property) AS speed FROM tgeometry WHERE collection_id = '{collection_id}' and mfeature_id = '{mfeature_id}' and tgeometry_id = '{tgeometry_id}'" # select_query = f"SELECT cumulativeLength(tgeometry_property) AS distance FROM tgeometry WHERE collection_id = '{collection_id}' and mfeature_id = '{mfeature_id}' and tgeometry_id = '{tgeometry_id}'" cursor.execute(select_query) rows = cursor.fetchall() @@ -680,16 +682,18 @@ def get_acceleration(self, collection_id, mfeature_id, tgeometry_id, datetime=No valueSequence = self.calculate_acceleration(each_values, each_time, datetime) if valueSequence.get("values"): - if interpolation == "Linear": + if datetime is not None: + valueSequence["interpolation"] = "Discrete" + elif interpolation == "Linear": valueSequence["interpolation"] = "Step" else: valueSequence["interpolation"] = interpolation tProperty["valueSequence"].append(valueSequence) return tProperty - def to_tProperties(self, rows, key, form, datetime): + def to_tProperties(self, rows, name, form, datetime): tProperty = { - "name": key, + "name": name, "type": "TReal", "form": form, "valueSequence": [] @@ -709,7 +713,7 @@ def to_tProperties(self, rows, key, form, datetime): valueSequence = { "datetimes": [format_datetime(datetime)], "values": [each_row[0]], - "interpolation": interpolation + "interpolation": "Discrete" } tProperty["valueSequence"].append(valueSequence) return tProperty diff --git a/sql/initdb-mobilitydb.sh b/sql/initdb-mobilitydb.sh index 9b4da72..0dfc3a1 100644 --- a/sql/initdb-mobilitydb.sh +++ b/sql/initdb-mobilitydb.sh @@ -34,7 +34,8 @@ psql --user="$POSTGRES_USER" --dbname="mobilitydb" <<- 'EOSQL' collection_id uuid NOT NULL, mfeature_id uuid NOT NULL, tgeometry_id uuid DEFAULT uuid_generate_v4 (), - tgeometry_property tgeogpoint NULL, + tgeometry_property tgeompoint NULL, + tgeog_property tgeogpoint NULL, PRIMARY KEY (collection_id, mfeature_id, tgeometry_id), FOREIGN KEY (collection_id, mfeature_id) REFERENCES mfeature(collection_id, mfeature_id) ); diff --git a/sql/mf-api.sql b/sql/mf-api.sql index 06e6657..8b75f4a 100644 --- a/sql/mf-api.sql +++ b/sql/mf-api.sql @@ -28,7 +28,8 @@ CREATE TABLE public.tgeometry collection_id uuid NOT NULL, mfeature_id uuid NOT NULL, tgeometry_id uuid DEFAULT uuid_generate_v4(), - tgeometry_property tgeogpoint NULL, + tgeometry_property tgeompoint NULL, + tgeog_property tgeogpoint NULL, PRIMARY KEY (collection_id, mfeature_id, tgeometry_id), FOREIGN KEY (collection_id, mfeature_id) REFERENCES mfeature (collection_id, mfeature_id) ); @@ -42,7 +43,7 @@ CREATE TABLE public.tproperties tproperties_name text NOT NULL, datetime_group int4 NOT NULL, tproperty jsonb NULL, - pvalue_float tfloat NULL, + pvalue_float tfloat NULL, pvalue_text ttext NULL, PRIMARY KEY (collection_id, mfeature_id, tproperties_name, datetime_group),