From 5990443eda07c70e30ce36e9516fcda646735755 Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Tue, 24 Jun 2025 15:20:23 +0800 Subject: [PATCH 1/4] update app --- dockerfiles/Dockerfile.dev.os | 3 +- .../stac_fastapi/elasticsearch/app.py | 83 +++++++++++------- .../opensearch/stac_fastapi/opensearch/app.py | 84 ++++++++++++------- 3 files changed, 107 insertions(+), 63 deletions(-) diff --git a/dockerfiles/Dockerfile.dev.os b/dockerfiles/Dockerfile.dev.os index a544e94a..a7fc113d 100644 --- a/dockerfiles/Dockerfile.dev.os +++ b/dockerfiles/Dockerfile.dev.os @@ -4,11 +4,10 @@ FROM python:3.10-slim # update apt pkgs, and install build-essential for ciso8601 RUN apt-get update && \ apt-get -y upgrade && \ - apt-get -y install build-essential && \ + apt-get -y install build-essential git && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* -RUN apt-get -y install git # update certs used by Requests ENV CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt diff --git a/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py b/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py index 7e145072..db88c87b 100644 --- a/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py +++ b/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py @@ -1,6 +1,5 @@ """FastAPI application.""" -import logging import os from contextlib import asynccontextmanager @@ -22,7 +21,6 @@ from stac_fastapi.core.rate_limit import setup_rate_limit from stac_fastapi.core.route_dependencies import get_route_dependencies from stac_fastapi.core.session import Session -from stac_fastapi.core.utilities import get_bool_env from stac_fastapi.elasticsearch.config import ElasticsearchSettings from stac_fastapi.elasticsearch.database_logic import ( DatabaseLogic, @@ -31,23 +29,23 @@ ) from stac_fastapi.extensions.core import ( AggregationExtension, + CollectionSearchExtension, + CollectionSearchFilterExtension, FilterExtension, FreeTextExtension, SortExtension, TokenPaginationExtension, TransactionExtension, ) +from stac_fastapi.extensions.core.fields import FieldsConformanceClasses from stac_fastapi.extensions.core.filter import FilterConformanceClasses +from stac_fastapi.extensions.core.free_text import FreeTextConformanceClasses +from stac_fastapi.extensions.core.query import QueryConformanceClasses +from stac_fastapi.extensions.core.sort import SortConformanceClasses from stac_fastapi.extensions.third_party import BulkTransactionExtension from stac_fastapi.sfeos_helpers.aggregation import EsAsyncBaseAggregationClient from stac_fastapi.sfeos_helpers.filter import EsAsyncBaseFiltersClient -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - -TRANSACTIONS_EXTENSIONS = get_bool_env("ENABLE_TRANSACTIONS_EXTENSIONS", default=True) -logger.info("TRANSACTIONS_EXTENSIONS is set to %s", TRANSACTIONS_EXTENSIONS) - settings = ElasticsearchSettings() session = Session.create_from_settings(settings) @@ -57,7 +55,7 @@ client=EsAsyncBaseFiltersClient(database=database_logic) ) filter_extension.conformance_classes.append( - FilterConformanceClasses.ADVANCED_COMPARISON_OPERATORS + "http://www.opengis.net/spec/cql2/1.0/conf/advanced-comparison-operators" ) aggregation_extension = AggregationExtension( @@ -69,6 +67,20 @@ aggregation_extension.GET = EsAggregationExtensionGetRequest search_extensions = [ + TransactionExtension( + client=TransactionsClient( + database=database_logic, session=session, settings=settings + ), + settings=settings, + ), + BulkTransactionExtension( + client=BulkTransactionsClient( + database=database_logic, + session=session, + settings=settings, + ) + ), + CollectionSearchExtension(), FieldsExtension(), QueryExtension(), SortExtension(), @@ -77,29 +89,40 @@ FreeTextExtension(), ] -if TRANSACTIONS_EXTENSIONS: - search_extensions.insert( - 0, - TransactionExtension( - client=TransactionsClient( - database=database_logic, session=session, settings=settings - ), - settings=settings, - ), - ) - search_extensions.insert( - 1, - BulkTransactionExtension( - client=BulkTransactionsClient( - database=database_logic, - session=session, - settings=settings, - ) - ), - ) - extensions = [aggregation_extension] + search_extensions +post_request_model = create_post_request_model(search_extensions) + +# Define the collection search extensions map +cs_extensions_map = { + "query": QueryExtension(conformance_classes=[QueryConformanceClasses.COLLECTIONS]), + "sort": SortExtension(conformance_classes=[SortConformanceClasses.COLLECTIONS]), + "fields": FieldsExtension( + conformance_classes=[FieldsConformanceClasses.COLLECTIONS] + ), + "filter": CollectionSearchFilterExtension( + conformance_classes=[FilterConformanceClasses.COLLECTIONS] + ), + "free_text": FreeTextExtension( + conformance_classes=[FreeTextConformanceClasses.COLLECTIONS], + ), +} + +# Determine enabled extensions (customize as needed) +enabled_extensions = set(cs_extensions_map.keys()) + +# Build the enabled collection search extensions +cs_extensions = [ + extension + for key, extension in cs_extensions_map.items() + if key in enabled_extensions +] + +# Create the CollectionSearchExtension from the enabled extensions +collection_search_extension = CollectionSearchExtension.from_extensions(cs_extensions) +collections_get_request_model = collection_search_extension.GET +extensions.append(collection_search_extension) + database_logic.extensions = [type(ext).__name__ for ext in extensions] post_request_model = create_post_request_model(search_extensions) diff --git a/stac_fastapi/opensearch/stac_fastapi/opensearch/app.py b/stac_fastapi/opensearch/stac_fastapi/opensearch/app.py index c047014a..7dd0da2c 100644 --- a/stac_fastapi/opensearch/stac_fastapi/opensearch/app.py +++ b/stac_fastapi/opensearch/stac_fastapi/opensearch/app.py @@ -1,6 +1,5 @@ """FastAPI application.""" -import logging import os from contextlib import asynccontextmanager @@ -22,16 +21,21 @@ from stac_fastapi.core.rate_limit import setup_rate_limit from stac_fastapi.core.route_dependencies import get_route_dependencies from stac_fastapi.core.session import Session -from stac_fastapi.core.utilities import get_bool_env from stac_fastapi.extensions.core import ( AggregationExtension, + CollectionSearchExtension, + CollectionSearchFilterExtension, FilterExtension, FreeTextExtension, SortExtension, TokenPaginationExtension, TransactionExtension, ) +from stac_fastapi.extensions.core.fields import FieldsConformanceClasses from stac_fastapi.extensions.core.filter import FilterConformanceClasses +from stac_fastapi.extensions.core.free_text import FreeTextConformanceClasses +from stac_fastapi.extensions.core.query import QueryConformanceClasses +from stac_fastapi.extensions.core.sort import SortConformanceClasses from stac_fastapi.extensions.third_party import BulkTransactionExtension from stac_fastapi.opensearch.config import OpensearchSettings from stac_fastapi.opensearch.database_logic import ( @@ -42,12 +46,6 @@ from stac_fastapi.sfeos_helpers.aggregation import EsAsyncBaseAggregationClient from stac_fastapi.sfeos_helpers.filter import EsAsyncBaseFiltersClient -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - -TRANSACTIONS_EXTENSIONS = get_bool_env("ENABLE_TRANSACTIONS_EXTENSIONS", default=True) -logger.info("TRANSACTIONS_EXTENSIONS is set to %s", TRANSACTIONS_EXTENSIONS) - settings = OpensearchSettings() session = Session.create_from_settings(settings) @@ -57,7 +55,7 @@ client=EsAsyncBaseFiltersClient(database=database_logic) ) filter_extension.conformance_classes.append( - FilterConformanceClasses.ADVANCED_COMPARISON_OPERATORS + "http://www.opengis.net/spec/cql2/1.0/conf/advanced-comparison-operators" ) aggregation_extension = AggregationExtension( @@ -69,6 +67,20 @@ aggregation_extension.GET = EsAggregationExtensionGetRequest search_extensions = [ + TransactionExtension( + client=TransactionsClient( + database=database_logic, session=session, settings=settings + ), + settings=settings, + ), + BulkTransactionExtension( + client=BulkTransactionsClient( + database=database_logic, + session=session, + settings=settings, + ) + ), + CollectionSearchExtension(), FieldsExtension(), QueryExtension(), SortExtension(), @@ -77,29 +89,39 @@ FreeTextExtension(), ] +extensions = [aggregation_extension] + search_extensions -if TRANSACTIONS_EXTENSIONS: - search_extensions.insert( - 0, - TransactionExtension( - client=TransactionsClient( - database=database_logic, session=session, settings=settings - ), - settings=settings, - ), - ) - search_extensions.insert( - 1, - BulkTransactionExtension( - client=BulkTransactionsClient( - database=database_logic, - session=session, - settings=settings, - ) - ), - ) +post_request_model = create_post_request_model(search_extensions) -extensions = [aggregation_extension] + search_extensions +# Define the collection search extensions map +cs_extensions_map = { + "query": QueryExtension(conformance_classes=[QueryConformanceClasses.COLLECTIONS]), + "sort": SortExtension(conformance_classes=[SortConformanceClasses.COLLECTIONS]), + "fields": FieldsExtension( + conformance_classes=[FieldsConformanceClasses.COLLECTIONS] + ), + "filter": CollectionSearchFilterExtension( + conformance_classes=[FilterConformanceClasses.COLLECTIONS] + ), + "free_text": FreeTextExtension( + conformance_classes=[FreeTextConformanceClasses.COLLECTIONS], + ), +} + +# Determine enabled extensions (customize as needed) +enabled_extensions = set(cs_extensions_map.keys()) + +# Build the enabled collection search extensions +cs_extensions = [ + extension + for key, extension in cs_extensions_map.items() + if key in enabled_extensions +] + +# Create the CollectionSearchExtension from the enabled extensions +collection_search_extension = CollectionSearchExtension.from_extensions(cs_extensions) +collections_get_request_model = collection_search_extension.GET +extensions.append(collection_search_extension) database_logic.extensions = [type(ext).__name__ for ext in extensions] @@ -146,7 +168,7 @@ def run() -> None: import uvicorn uvicorn.run( - "stac_fastapi.opensearch.app:app", + "stac_fastapi.elasticsearch.app:app", host=settings.app_host, port=settings.app_port, log_level="info", From 898baf6f7e666ec311b8e4d1c73b7170b1ac1efb Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Tue, 24 Jun 2025 16:03:08 +0800 Subject: [PATCH 2/4] update --- .../stac_fastapi/elasticsearch/app.py | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py b/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py index db88c87b..f1f5fd97 100644 --- a/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py +++ b/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py @@ -1,5 +1,6 @@ """FastAPI application.""" +import logging import os from contextlib import asynccontextmanager @@ -21,6 +22,7 @@ from stac_fastapi.core.rate_limit import setup_rate_limit from stac_fastapi.core.route_dependencies import get_route_dependencies from stac_fastapi.core.session import Session +from stac_fastapi.core.utilities import get_bool_env from stac_fastapi.elasticsearch.config import ElasticsearchSettings from stac_fastapi.elasticsearch.database_logic import ( DatabaseLogic, @@ -46,6 +48,12 @@ from stac_fastapi.sfeos_helpers.aggregation import EsAsyncBaseAggregationClient from stac_fastapi.sfeos_helpers.filter import EsAsyncBaseFiltersClient +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +TRANSACTIONS_EXTENSIONS = get_bool_env("ENABLE_TRANSACTIONS_EXTENSIONS", default=True) +logger.info("TRANSACTIONS_EXTENSIONS is set to %s", TRANSACTIONS_EXTENSIONS) + settings = ElasticsearchSettings() session = Session.create_from_settings(settings) @@ -55,9 +63,8 @@ client=EsAsyncBaseFiltersClient(database=database_logic) ) filter_extension.conformance_classes.append( - "http://www.opengis.net/spec/cql2/1.0/conf/advanced-comparison-operators" + FilterConformanceClasses.ADVANCED_COMPARISON_OPERATORS ) - aggregation_extension = AggregationExtension( client=EsAsyncBaseAggregationClient( database=database_logic, session=session, settings=settings @@ -67,19 +74,6 @@ aggregation_extension.GET = EsAggregationExtensionGetRequest search_extensions = [ - TransactionExtension( - client=TransactionsClient( - database=database_logic, session=session, settings=settings - ), - settings=settings, - ), - BulkTransactionExtension( - client=BulkTransactionsClient( - database=database_logic, - session=session, - settings=settings, - ) - ), CollectionSearchExtension(), FieldsExtension(), QueryExtension(), @@ -89,9 +83,28 @@ FreeTextExtension(), ] -extensions = [aggregation_extension] + search_extensions +if TRANSACTIONS_EXTENSIONS: + search_extensions.insert( + 0, + TransactionExtension( + client=TransactionsClient( + database=database_logic, session=session, settings=settings + ), + settings=settings, + ), + ) + search_extensions.insert( + 1, + BulkTransactionExtension( + client=BulkTransactionsClient( + database=database_logic, + session=session, + settings=settings, + ) + ), + ) -post_request_model = create_post_request_model(search_extensions) +extensions = [aggregation_extension] + search_extensions # Define the collection search extensions map cs_extensions_map = { From 90f25de50c58f1afd1be470b96afa34e54742b46 Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Tue, 24 Jun 2025 19:04:00 +0800 Subject: [PATCH 3/4] reorg --- .../stac_fastapi/elasticsearch/app.py | 43 ++++----- .../opensearch/stac_fastapi/opensearch/app.py | 92 ++++++++++--------- stac_fastapi/tests/conftest.py | 76 +++++---------- 3 files changed, 89 insertions(+), 122 deletions(-) diff --git a/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py b/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py index f1f5fd97..e9ff23e3 100644 --- a/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py +++ b/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py @@ -73,8 +73,8 @@ aggregation_extension.POST = EsAggregationExtensionPostRequest aggregation_extension.GET = EsAggregationExtensionGetRequest +# Base search extensions (without CollectionSearchExtension to avoid duplicates) search_extensions = [ - CollectionSearchExtension(), FieldsExtension(), QueryExtension(), SortExtension(), @@ -104,37 +104,28 @@ ), ) +# Initialize extensions with just the search and aggregation extensions +# Initialize with base extensions extensions = [aggregation_extension] + search_extensions -# Define the collection search extensions map -cs_extensions_map = { - "query": QueryExtension(conformance_classes=[QueryConformanceClasses.COLLECTIONS]), - "sort": SortExtension(conformance_classes=[SortConformanceClasses.COLLECTIONS]), - "fields": FieldsExtension( - conformance_classes=[FieldsConformanceClasses.COLLECTIONS] - ), - "filter": CollectionSearchFilterExtension( +# Create collection search extensions +collection_search_extensions = [ + QueryExtension(conformance_classes=[QueryConformanceClasses.COLLECTIONS]), + SortExtension(conformance_classes=[SortConformanceClasses.COLLECTIONS]), + FieldsExtension(conformance_classes=[FieldsConformanceClasses.COLLECTIONS]), + CollectionSearchFilterExtension( conformance_classes=[FilterConformanceClasses.COLLECTIONS] ), - "free_text": FreeTextExtension( - conformance_classes=[FreeTextConformanceClasses.COLLECTIONS], - ), -} - -# Determine enabled extensions (customize as needed) -enabled_extensions = set(cs_extensions_map.keys()) - -# Build the enabled collection search extensions -cs_extensions = [ - extension - for key, extension in cs_extensions_map.items() - if key in enabled_extensions + FreeTextExtension(conformance_classes=[FreeTextConformanceClasses.COLLECTIONS]), ] -# Create the CollectionSearchExtension from the enabled extensions -collection_search_extension = CollectionSearchExtension.from_extensions(cs_extensions) -collections_get_request_model = collection_search_extension.GET -extensions.append(collection_search_extension) +# Initialize collection search with its extensions +collection_search_ext = CollectionSearchExtension.from_extensions( + collection_search_extensions +) +collections_get_request_model = collection_search_ext.GET + +extensions.append(collection_search_ext) database_logic.extensions = [type(ext).__name__ for ext in extensions] diff --git a/stac_fastapi/opensearch/stac_fastapi/opensearch/app.py b/stac_fastapi/opensearch/stac_fastapi/opensearch/app.py index 7dd0da2c..dd73384b 100644 --- a/stac_fastapi/opensearch/stac_fastapi/opensearch/app.py +++ b/stac_fastapi/opensearch/stac_fastapi/opensearch/app.py @@ -1,5 +1,6 @@ """FastAPI application.""" +import logging import os from contextlib import asynccontextmanager @@ -21,6 +22,7 @@ from stac_fastapi.core.rate_limit import setup_rate_limit from stac_fastapi.core.route_dependencies import get_route_dependencies from stac_fastapi.core.session import Session +from stac_fastapi.core.utilities import get_bool_env from stac_fastapi.extensions.core import ( AggregationExtension, CollectionSearchExtension, @@ -46,6 +48,12 @@ from stac_fastapi.sfeos_helpers.aggregation import EsAsyncBaseAggregationClient from stac_fastapi.sfeos_helpers.filter import EsAsyncBaseFiltersClient +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +TRANSACTIONS_EXTENSIONS = get_bool_env("ENABLE_TRANSACTIONS_EXTENSIONS", default=True) +logger.info("TRANSACTIONS_EXTENSIONS is set to %s", TRANSACTIONS_EXTENSIONS) + settings = OpensearchSettings() session = Session.create_from_settings(settings) @@ -55,9 +63,8 @@ client=EsAsyncBaseFiltersClient(database=database_logic) ) filter_extension.conformance_classes.append( - "http://www.opengis.net/spec/cql2/1.0/conf/advanced-comparison-operators" + FilterConformanceClasses.ADVANCED_COMPARISON_OPERATORS ) - aggregation_extension = AggregationExtension( client=EsAsyncBaseAggregationClient( database=database_logic, session=session, settings=settings @@ -66,21 +73,8 @@ aggregation_extension.POST = EsAggregationExtensionPostRequest aggregation_extension.GET = EsAggregationExtensionGetRequest +# Base search extensions (without CollectionSearchExtension to avoid duplicates) search_extensions = [ - TransactionExtension( - client=TransactionsClient( - database=database_logic, session=session, settings=settings - ), - settings=settings, - ), - BulkTransactionExtension( - client=BulkTransactionsClient( - database=database_logic, - session=session, - settings=settings, - ) - ), - CollectionSearchExtension(), FieldsExtension(), QueryExtension(), SortExtension(), @@ -89,39 +83,49 @@ FreeTextExtension(), ] -extensions = [aggregation_extension] + search_extensions +if TRANSACTIONS_EXTENSIONS: + search_extensions.insert( + 0, + TransactionExtension( + client=TransactionsClient( + database=database_logic, session=session, settings=settings + ), + settings=settings, + ), + ) + search_extensions.insert( + 1, + BulkTransactionExtension( + client=BulkTransactionsClient( + database=database_logic, + session=session, + settings=settings, + ) + ), + ) -post_request_model = create_post_request_model(search_extensions) +# Initialize extensions with just the search and aggregation extensions +# Initialize with base extensions +extensions = [aggregation_extension] + search_extensions -# Define the collection search extensions map -cs_extensions_map = { - "query": QueryExtension(conformance_classes=[QueryConformanceClasses.COLLECTIONS]), - "sort": SortExtension(conformance_classes=[SortConformanceClasses.COLLECTIONS]), - "fields": FieldsExtension( - conformance_classes=[FieldsConformanceClasses.COLLECTIONS] - ), - "filter": CollectionSearchFilterExtension( +# Create collection search extensions +collection_search_extensions = [ + QueryExtension(conformance_classes=[QueryConformanceClasses.COLLECTIONS]), + SortExtension(conformance_classes=[SortConformanceClasses.COLLECTIONS]), + FieldsExtension(conformance_classes=[FieldsConformanceClasses.COLLECTIONS]), + CollectionSearchFilterExtension( conformance_classes=[FilterConformanceClasses.COLLECTIONS] ), - "free_text": FreeTextExtension( - conformance_classes=[FreeTextConformanceClasses.COLLECTIONS], - ), -} - -# Determine enabled extensions (customize as needed) -enabled_extensions = set(cs_extensions_map.keys()) - -# Build the enabled collection search extensions -cs_extensions = [ - extension - for key, extension in cs_extensions_map.items() - if key in enabled_extensions + FreeTextExtension(conformance_classes=[FreeTextConformanceClasses.COLLECTIONS]), ] -# Create the CollectionSearchExtension from the enabled extensions -collection_search_extension = CollectionSearchExtension.from_extensions(cs_extensions) -collections_get_request_model = collection_search_extension.GET -extensions.append(collection_search_extension) +# Initialize collection search with its extensions +collection_search_ext = CollectionSearchExtension.from_extensions( + collection_search_extensions +) +collections_get_request_model = collection_search_ext.GET + +extensions.append(collection_search_ext) database_logic.extensions = [type(ext).__name__ for ext in extensions] @@ -168,7 +172,7 @@ def run() -> None: import uvicorn uvicorn.run( - "stac_fastapi.elasticsearch.app:app", + "stac_fastapi.opensearch.app:app", host=settings.app_host, port=settings.app_port, log_level="info", diff --git a/stac_fastapi/tests/conftest.py b/stac_fastapi/tests/conftest.py index d8c5fc88..c5cdbd2e 100644 --- a/stac_fastapi/tests/conftest.py +++ b/stac_fastapi/tests/conftest.py @@ -18,14 +18,9 @@ CoreClient, TransactionsClient, ) -from stac_fastapi.core.extensions import QueryExtension -from stac_fastapi.core.extensions.aggregation import ( - EsAggregationExtensionGetRequest, - EsAggregationExtensionPostRequest, -) from stac_fastapi.core.rate_limit import setup_rate_limit from stac_fastapi.core.utilities import get_bool_env -from stac_fastapi.sfeos_helpers.aggregation import EsAsyncBaseAggregationClient +from stac_fastapi.extensions.third_party import BulkTransactionExtension if os.getenv("BACKEND", "elasticsearch").lower() == "opensearch": from stac_fastapi.opensearch.app import app_config @@ -50,15 +45,7 @@ create_index_templates, ) -from stac_fastapi.extensions.core import ( - AggregationExtension, - FieldsExtension, - FilterExtension, - FreeTextExtension, - SortExtension, - TokenPaginationExtension, - TransactionExtension, -) +from stac_fastapi.extensions.core import TransactionExtension from stac_fastapi.types.config import Settings DATA_DIR = os.path.join(os.path.dirname(__file__), "data") @@ -340,7 +327,7 @@ async def route_dependencies_client(route_dependencies_app): def build_test_app(): """Build a test app with configurable transaction extensions.""" - # Create a copy of the base config + # Create a copy of the base config which already has all extensions configured test_config = app_config.copy() # Get transaction extensions setting @@ -348,48 +335,33 @@ def build_test_app(): "ENABLE_TRANSACTIONS_EXTENSIONS", default=True ) - # Configure extensions - settings = AsyncSettings() - aggregation_extension = AggregationExtension( - client=EsAsyncBaseAggregationClient( - database=database, session=None, settings=settings - ) - ) - aggregation_extension.POST = EsAggregationExtensionPostRequest - aggregation_extension.GET = EsAggregationExtensionGetRequest - - search_extensions = [ - SortExtension(), - FieldsExtension(), - QueryExtension(), - TokenPaginationExtension(), - FilterExtension(), - FreeTextExtension(), - ] + # First remove any existing transaction extensions + if "extensions" in test_config: + test_config["extensions"] = [ + ext + for ext in test_config["extensions"] + if not isinstance(ext, (TransactionExtension, BulkTransactionExtension)) + ] # Add transaction extension if enabled if TRANSACTIONS_EXTENSIONS: - search_extensions.append( - TransactionExtension( - client=TransactionsClient( - database=database, session=None, settings=settings + settings = AsyncSettings() + test_config["extensions"].extend( + [ + TransactionExtension( + client=TransactionsClient( + database=database, session=None, settings=settings + ), + settings=settings, + ), + BulkTransactionExtension( + client=BulkTransactionsClient( + database=database, session=None, settings=settings + ) ), - settings=settings, - ) + ] ) - # Update extensions in config - extensions = [aggregation_extension] + search_extensions - test_config["extensions"] = extensions - - # Update client with new extensions - test_config["client"] = CoreClient( - database=database, - session=None, - extensions=extensions, - post_request_model=test_config["search_post_request_model"], - ) - # Create and return the app api = StacApi(**test_config) return api.app From 80ae53fad68893b509656f5053356cd055ef314e Mon Sep 17 00:00:00 2001 From: jonhealy1 Date: Wed, 25 Jun 2025 13:38:46 +0800 Subject: [PATCH 4/4] update collections mappings --- CHANGELOG.md | 4 ++++ .../stac_fastapi/sfeos_helpers/mappings.py | 13 +++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 979094a4..dc2e463f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +### Added + +- Added support for Collections search + ## [v6.0.0] - 2025-06-22 ### Added diff --git a/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/mappings.py b/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/mappings.py index 476d656a..6428f9db 100644 --- a/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/mappings.py +++ b/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/mappings.py @@ -158,8 +158,17 @@ class Geometry(Protocol): # noqa "dynamic_templates": ES_MAPPINGS_DYNAMIC_TEMPLATES, "properties": { "id": {"type": "keyword"}, - "extent.spatial.bbox": {"type": "long"}, - "extent.temporal.interval": {"type": "date"}, + "bbox_shape": {"type": "geo_shape"}, # Only this is used for spatial queries + "extent": { + "properties": {"temporal": {"properties": {"interval": {"type": "date"}}}} + }, + "properties": { + "properties": { + "datetime": {"type": "date"}, + "start_datetime": {"type": "date"}, + "end_datetime": {"type": "date"}, + } + }, "providers": {"type": "object", "enabled": False}, "links": {"type": "object", "enabled": False}, "item_assets": {"type": "object", "enabled": False},