diff --git a/CHANGES.md b/CHANGES.md index 870f0a46..5bf9bdf7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,7 +4,7 @@ ### Changed -- Handle `next` and `dev` tokens now returned as links from pgstac>=0.9.0 (author @zstatmanweil, https://github.com/stac-utils/stac-fastapi-pgstac/pull/140) +- Handle `next` and `dev` tokens now returned as links from pgstac>=0.9.0 (author @zstatmanweil, ) - Add collection search extension ([#139](https://github.com/stac-utils/stac-fastapi-pgstac/pull/139)) - keep `/search` and `/collections` extensions separate ([#158](https://github.com/stac-utils/stac-fastapi-pgstac/pull/158)) - update `pypgstac` requirement to `>=0.8,<0.10` @@ -15,6 +15,7 @@ - changed `datetime` input type to `string` in GET endpoint methods - renamed `filter` to `filter_expr` input attributes in GET endpoint methods - delete `utils.format_datetime_range` function +- add [free-text extension](https://github.com/stac-api-extensions/freetext-search) to collection search extensions ([#162](https://github.com/stac-utils/stac-fastapi-pgstac/pull/162)) ### Fixed @@ -23,7 +24,7 @@ ## [3.0.1] - 2024-11-14 -- Enable runtime `CORS` configuration using environment variables (`CORS_ORIGIN="https://...,https://..."`, `CORS_METHODS="PUT,OPTIONS"`) (https://github.com/stac-utils/stac-fastapi-pgstac/pull/168) +- Enable runtime `CORS` configuration using environment variables (`CORS_ORIGIN="https://...,https://..."`, `CORS_METHODS="PUT,OPTIONS"`) () ## [3.0.0] - 2024-08-02 diff --git a/stac_fastapi/pgstac/app.py b/stac_fastapi/pgstac/app.py index 069d9723..d45ba9ec 100644 --- a/stac_fastapi/pgstac/app.py +++ b/stac_fastapi/pgstac/app.py @@ -24,6 +24,7 @@ from stac_fastapi.extensions.core import ( FieldsExtension, FilterExtension, + FreeTextExtension, OffsetPaginationExtension, SortExtension, TokenPaginationExtension, @@ -62,6 +63,7 @@ "sort": SortExtension(), "fields": FieldsExtension(), "filter": FilterExtension(client=FiltersClient()), + "free_text": FreeTextExtension(), "pagination": OffsetPaginationExtension(), } diff --git a/stac_fastapi/pgstac/core.py b/stac_fastapi/pgstac/core.py index 12455e45..efc10cf5 100644 --- a/stac_fastapi/pgstac/core.py +++ b/stac_fastapi/pgstac/core.py @@ -54,6 +54,7 @@ async def all_collections( # noqa: C901 sortby: Optional[str] = None, filter_expr: Optional[str] = None, filter_lang: Optional[str] = None, + q: Optional[List[str]] = None, **kwargs, ) -> Collections: """Cross catalog search (GET). @@ -85,6 +86,7 @@ async def all_collections( # noqa: C901 sortby=sortby, filter_query=filter_expr, filter_lang=filter_lang, + q=q, ) async with request.app.state.get_connection(request, "r") as conn: @@ -508,6 +510,7 @@ def _clean_search_args( # noqa: C901 sortby: Optional[str] = None, filter_query: Optional[str] = None, filter_lang: Optional[str] = None, + q: Optional[List[str]] = None, ) -> Dict[str, Any]: """Clean up search arguments to match format expected by pgstac""" if filter_query: @@ -551,6 +554,9 @@ def _clean_search_args( # noqa: C901 base_args["fields"] = {"include": includes, "exclude": excludes} + if q: + base_args["q"] = " OR ".join(q) + # Remove None values from dict clean = {} for k, v in base_args.items(): diff --git a/tests/conftest.py b/tests/conftest.py index f6b272f4..d6592d9d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -27,6 +27,7 @@ CollectionSearchExtension, FieldsExtension, FilterExtension, + FreeTextExtension, OffsetPaginationExtension, SortExtension, TokenPaginationExtension, @@ -148,6 +149,7 @@ def api_client(request, database): SortExtension(), FieldsExtension(), FilterExtension(client=FiltersClient()), + FreeTextExtension(), OffsetPaginationExtension(), ] collection_search_extension = CollectionSearchExtension.from_extensions( diff --git a/tests/resources/test_collection.py b/tests/resources/test_collection.py index dec20881..d25ed638 100644 --- a/tests/resources/test_collection.py +++ b/tests/resources/test_collection.py @@ -307,6 +307,26 @@ async def test_get_collections_search( assert len(resp.json()["collections"]) == 2 +@requires_pgstac_0_9_2 +@pytest.mark.asyncio +async def test_collection_search_freetext( + app_client, load_test_collection, load_test2_collection +): + # free-text + resp = await app_client.get( + "/collections", + params={"q": "temperature"}, + ) + assert len(resp.json()["collections"]) == 1 + assert resp.json()["collections"][0]["id"] == load_test2_collection.id + + resp = await app_client.get( + "/collections", + params={"q": "nosuchthing"}, + ) + assert len(resp.json()["collections"]) == 0 + + @requires_pgstac_0_9_2 @pytest.mark.asyncio async def test_all_collections_with_pagination(app_client, load_test_data):