diff --git a/tests/fixtures/timeseries/timeseries.json b/tests/fixtures/timeseries/timeseries.json index bd7c59b1699ffe7f33baa9d0e139714d5b77412a..47e89337793c5427ee7e9d1ae27003434910d324 100644 --- a/tests/fixtures/timeseries/timeseries.json +++ b/tests/fixtures/timeseries/timeseries.json @@ -11,7 +11,7 @@ "data_origin": 0, "data_origin_type": 0, "sampling_height": 7, - "additional_metadata": {}, + "additional_metadata": {"original_units": "ppb"}, "programme_id": 0 }, { diff --git a/tests/test_data.py b/tests/test_data.py index b49a45623abb72268326abaa074baa2e51e8bddf..da4e3acfd73820e8920291e25cb9457bd934f0e9 100644 --- a/tests/test_data.py +++ b/tests/test_data.py @@ -206,7 +206,7 @@ class TestApps: 'doi': '', 'data_start_date': '2003-09-07T15:30:00+00:00', 'data_end_date': '2016-12-31T14:30:00+00:00', 'coverage': -1.0, 'data_origin': 'instrument', 'data_origin_type': 'measurement', 'provider_version': 'N/A', - 'sampling_height': 7.0, 'additional_metadata': {}, + 'sampling_height': 7.0, 'additional_metadata': {'original_units': 'ppb'}, 'station': {'id': 2, 'codes': ['SDZ54421'], 'name': 'Shangdianzi', 'coordinates': {'lat': 40.65, 'lng': 117.106, 'alt': 293.9}, 'coordinate_validation_status': 'not checked', 'country': 'China', 'state': 'Beijing Shi', 'type': 'unknown', 'type_of_area': 'unknown', 'timezone': 'Asia/Shanghai', @@ -270,7 +270,7 @@ class TestApps: 'data_origin_type': 'measurement', 'provider_version': 'N/A', 'sampling_height': 7.0, - 'additional_metadata': {}, + 'additional_metadata': {'original_units': 'ppb'}, 'doi': '', 'coverage': -1.0, 'station': {'id': 2, @@ -354,7 +354,7 @@ class TestApps: 'data_origin_type': 'measurement', 'provider_version': 'N/A', 'sampling_height': 7.0, - 'additional_metadata': {}, + 'additional_metadata': {'original_units': 'ppb'}, 'doi': '', 'coverage': -1.0, 'station': {'id': 2, @@ -433,7 +433,9 @@ class TestApps: '# "data_origin_type": "measurement",\n', '# "provider_version": "N/A",\n', '# "sampling_height": 7.0,\n', - '# "additional_metadata": {},\n', + '# "additional_metadata": {\n', + '# "original_units": "ppb"\n', + '# },\n', '# "data_license_accepted": null,\n', '# "dataset_approved_by_provider": null,\n', '# "doi": "",\n', @@ -624,7 +626,7 @@ class TestApps: 'license': 'This data is published under a Creative Commons Attribution 4.0 International (CC BY 4.0). https://creativecommons.org/licenses/by/4.0/', 'doi': '', 'data_start_date': '2003-09-07T15:30:00+00:00', 'data_end_date': '2016-12-31T14:30:00+00:00', 'coverage': -1.0, 'data_origin': 'instrument', - 'data_origin_type': 'measurement', 'provider_version': 'N/A', 'sampling_height': 7.0, 'additional_metadata': {}, + 'data_origin_type': 'measurement', 'provider_version': 'N/A', 'sampling_height': 7.0, 'additional_metadata': {'original_units': 'ppb'}, 'station': {'id': 2, 'codes': ['SDZ54421'], 'name': 'Shangdianzi', 'coordinates': {'lat': 40.65, 'lng': 117.106, 'alt': 293.9}, 'coordinate_validation_status': 'not checked', 'country': 'China', 'state': 'Beijing Shi', 'type': 'unknown', 'type_of_area': 'unknown', 'timezone': 'Asia/Shanghai', @@ -1003,7 +1005,7 @@ class TestApps: 'data_origin_type': 'measurement', 'provider_version': 'N/A', 'sampling_height': 7.0, - 'additional_metadata': {}, + 'additional_metadata': {'original_units': 'ppb'}, 'station': {'id': 2, 'codes': ['SDZ54421'], 'name': 'Shangdianzi', diff --git a/tests/test_search.py b/tests/test_search.py index f1298459c496e5b10262e6c0478ff99489f2347a..b3c32a3ca01e063402208c2b7a5bb1f9c1175c2f 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -187,7 +187,7 @@ class TestApps: 'data_origin_type': 'measurement', 'provider_version': 'N/A', 'sampling_height': 7.0, - 'additional_metadata': {}, + 'additional_metadata': {"original_units": "ppb"}, 'doi': '', 'coverage': -1.0, 'station': {'id': 2, @@ -675,7 +675,7 @@ class TestApps: assert response.status_code == expected_status_code expected_resp = [{'id': 1, 'order': 1, - 'additional_metadata': {}, + 'additional_metadata': {"original_units": "ppb"}, 'roles': {'role': 'resource provider', 'status': 'active', 'contact_id': 4} }, {'id': 2, @@ -999,6 +999,93 @@ class TestApps: assert response.json() == expected_response + def test_search_with_additional_metadata3(self, client, db): + response = client.get("/search/?additional_metadata->'original_units'=ppb") + expected_status_code = 200 + assert response.status_code == expected_status_code + expected_response = [{'id': 1, + 'label': 'CMA', + 'order': 1, + 'sampling_frequency': 'hourly', + 'aggregation': 'mean', + 'data_start_date': '2003-09-07T15:30:00+00:00', + 'data_end_date': '2016-12-31T14:30:00+00:00', + 'data_origin': 'instrument', + 'data_origin_type': 'measurement', + 'provider_version': 'N/A', + 'sampling_height': 7.0, + 'additional_metadata': {"original_units": "ppb"}, + 'doi': '', + 'coverage': -1.0, + 'station': {'id': 2, + 'codes': ['SDZ54421'], + 'name': 'Shangdianzi', + 'coordinates': {'lat': 40.65, 'lng': 117.106, 'alt': 293.9}, + 'coordinate_validation_status': 'not checked', + 'country': 'China', + 'state': 'Beijing Shi', + 'type': 'unknown', + 'type_of_area': 'unknown', + 'timezone': 'Asia/Shanghai', + 'additional_metadata': {'add_type': 'nature reservation'}, + 'aux_images': [], + 'aux_docs': [], + 'aux_urls': [], + 'globalmeta': {'mean_topography_srtm_alt_90m_year1994': -999.0, + 'mean_topography_srtm_alt_1km_year1994': -999.0, + 'max_topography_srtm_relative_alt_5km_year1994': -999.0, + 'min_topography_srtm_relative_alt_5km_year1994': -999.0, + 'stddev_topography_srtm_relative_alt_5km_year1994': -999.0, + 'climatic_zone_year2016': '6 (warm temperate dry)', + 'htap_region_tier1_year2010': '11 (MDE Middle East: S. Arabia, Oman, etc, Iran, Iraq)', + 'dominant_landcover_year2012': '11 (Cropland, rainfed, herbaceous cover)', + 'landcover_description_25km_year2012': '', + 'dominant_ecoregion_year2017': '-1 (undefined)', + 'ecoregion_description_25km_year2017': '', + 'distance_to_major_road_year2020': -999.0, + 'mean_stable_nightlights_1km_year2013': -999.0, + 'mean_stable_nightlights_5km_year2013': -999.0, + 'max_stable_nightlights_25km_year2013': -999.0, + 'max_stable_nightlights_25km_year1992': -999.0, + 'mean_population_density_250m_year2015': -1.0, + 'mean_population_density_5km_year2015': -1.0, + 'max_population_density_25km_year2015': -1.0, + 'mean_population_density_250m_year1990': -1.0, + 'mean_population_density_5km_year1990': -1.0, + 'max_population_density_25km_year1990': -1.0, + 'mean_nox_emissions_10km_year2015': -999.0, + 'mean_nox_emissions_10km_year2000': -999.0, + 'toar1_category': 'unclassified'}, + 'changelog': [{'datetime': '2023-07-15T19:27:09.463245+00:00', 'description': 'station created', 'old_value': '', 'new_value': '', 'station_id': 2, 'author_id': 1, 'type_of_change': 'created'}]}, + 'variable': {'name': 'toluene', + 'longname': 'toluene', + 'displayname': 'Toluene', + 'cf_standardname': 'mole_fraction_of_toluene_in_air', + 'units': 'nmol mol-1', + 'chemical_formula': 'C7H8', + 'id': 7}, + 'programme': {'id': 0, + 'name': '', + 'longname': '', + 'homepage': '', + 'description': ''}, + 'roles': [{'id': 2, + 'role': 'resource provider', + 'status': 'active', + 'contact': {'id': 4, + 'organisation': {'id': 1, + 'name': 'UBA', + 'longname': 'Umweltbundesamt', + 'kind': 'government', + 'city': 'Dessau-Roßlau', + 'postcode': '06844', + 'street_address': 'Wörlitzer Platz 1', + 'country': 'Germany', + 'homepage': 'https://www.umweltbundesamt.de', + 'contact_url': 'mailto:immission@uba.de'}}}]}] + assert response.json() == expected_response + + def test_search_with_additional_metadata_unknown(self, client, db): response = client.get("/search/?additional_metadata->'not_yet_defined'=42") expected_status_code = 200 @@ -1022,7 +1109,7 @@ class TestApps: 'data_origin_type': 'measurement', 'provider_version': 'N/A', 'sampling_height': 7.0, - 'additional_metadata': {}, + 'additional_metadata': {"original_units": "ppb"}, 'doi': '', 'coverage': -1.0, 'station': {'id': 2, diff --git a/tests/test_timeseries.py b/tests/test_timeseries.py index 672d3b9e83ec0e01b8fe566579fd9a9762fe1722..6f9c5278d8d76d086fa0ea675538c5bd6adfa5ba 100644 --- a/tests/test_timeseries.py +++ b/tests/test_timeseries.py @@ -189,7 +189,7 @@ class TestApps: 'data_origin_type': 'measurement', 'provider_version': 'N/A', 'sampling_height': 7.0, - 'additional_metadata': {}, + 'additional_metadata': {'original_units': 'ppb'}, 'doi': '', 'coverage': -1.0, 'station': {'id': 2, @@ -380,7 +380,7 @@ class TestApps: 'sampling_frequency': 'hourly', 'aggregation': 'mean', 'data_origin_type': 'measurement', 'data_start_date': '2003-09-07T15:30:00+00:00', 'data_end_date': '2016-12-31T14:30:00+00:00', 'coverage': -1.0, 'data_origin': 'instrument', 'sampling_height': 7.0, - 'provider_version': 'N/A', 'doi': '', 'additional_metadata': {}, + 'provider_version': 'N/A', 'doi': '', 'additional_metadata': {'original_units': 'ppb'}, 'roles': [{'id': 2, 'role': 'resource provider', 'status': 'active', 'contact': {'id': 4, 'organisation': {'id': 1, 'name': 'UBA', 'longname': 'Umweltbundesamt', 'kind': 'government', 'city': 'Dessau-Roßlau', 'postcode': '06844', 'street_address': 'Wörlitzer Platz 1', @@ -603,7 +603,7 @@ class TestApps: 'id': 1, 'label': 'CMA', 'order': 1, 'sampling_frequency': 'hourly', 'aggregation': 'mean', 'data_start_date': '2003-09-07T15:30:00+00:00', 'data_end_date': '2016-12-31T14:30:00+00:00', 'coverage': -1.0, 'data_origin': 'instrument', 'data_origin_type': 'measurement', - 'provider_version': 'N/A', 'doi': '', 'sampling_height': 7.0, 'additional_metadata': {}, + 'provider_version': 'N/A', 'doi': '', 'sampling_height': 7.0, 'additional_metadata': {'original_units': 'ppb'}, 'roles': [{'id': 2, 'role': 'resource provider', 'status': 'active', 'contact': {'id': 4, 'organisation': {'id': 1, 'name': 'UBA', 'longname': 'Umweltbundesamt', 'kind': 'government', 'city': 'Dessau-Roßlau', 'postcode': '06844', 'street_address': 'Wörlitzer Platz 1', @@ -653,7 +653,7 @@ class TestApps: response = client.get("/timeseries/1?fields=additional_metadata") expected_status_code = 200 assert response.status_code == expected_status_code - expected_response = {'additional_metadata': {} } + expected_response = {'additional_metadata': {'original_units': 'ppb'} } assert response.json() == expected_response @@ -662,7 +662,7 @@ class TestApps: expected_status_code = 200 assert response.status_code == expected_status_code expected_response = [ - {'additional_metadata': {}}, + {'additional_metadata': {'original_units': 'ppb'}}, {'additional_metadata': {'absorption_cross_section': 'Hearn 1961', 'ebas_metadata_19740101000000_29y': @@ -696,7 +696,7 @@ class TestApps: 'data_origin_type': 'measurement', 'provider_version': 'N/A', 'sampling_height': 7.0, - 'additional_metadata': {}, + 'additional_metadata': {'original_units': 'ppb'}, 'doi': '', 'coverage': -1.0, 'station': {'id': 2, diff --git a/toardb/utils/utils.py b/toardb/utils/utils.py index d2da351446b21c74b68c475b6c675d928ba78506..b41ab05628822d61102b012bf8e15218d1aae5a6 100644 --- a/toardb/utils/utils.py +++ b/toardb/utils/utils.py @@ -289,12 +289,19 @@ def create_filter(query_params, endpoint): if param == "additional_metadata->'absorption_cross_section'": trlist = translate_convoc_list(values, toardb.toardb.CS_vocabulary, "absorption_cross_section") values = [ str(val) for val in trlist ] - if param == "additional_metadata->'sampling_type'": + param = f"timeseries.{param}" + elif param == "additional_metadata->'sampling_type'": trlist = translate_convoc_list(values, toardb.toardb.KS_vocabulary, "sampling_type") values = [ str(val) for val in trlist ] - if param == "additional_metadata->'calibration_type'": + param = f"timeseries.{param}" + elif param == "additional_metadata->'calibration_type'": trlist = translate_convoc_list(values, toardb.toardb.CT_vocabulary, "calibration_type") values = [ str(val) for val in trlist ] + param = f"timeseries.{param}" + else: + val_mod = [ f"'\"{val}\"'::text" for val in values ] + values = "(" + ",".join(val_mod) + ")" + param = f"to_json(timeseries.{param})::text" if param == "has_role": operator = "IN" join_operator = "OR" @@ -311,6 +318,8 @@ def create_filter(query_params, endpoint): t_r_filter.append(f"persons.name {operator} {values}") t_r_filter.append(f"persons.orcid {operator} {values}") t_r_filter = f" {join_operator} ".join(t_r_filter) + elif param_long.split('>')[0] == "additional_metadata-": + t_filter.append(f"{param} IN {values}") else: t_filter.append(f"timeseries.{param} IN {values}") elif param in data_params: