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/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..e9ff23e3 100644 --- a/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py +++ b/stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py @@ -31,13 +31,19 @@ ) 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 @@ -59,7 +65,6 @@ filter_extension.conformance_classes.append( FilterConformanceClasses.ADVANCED_COMPARISON_OPERATORS ) - aggregation_extension = AggregationExtension( client=EsAsyncBaseAggregationClient( database=database_logic, session=session, settings=settings @@ -68,6 +73,7 @@ aggregation_extension.POST = EsAggregationExtensionPostRequest aggregation_extension.GET = EsAggregationExtensionGetRequest +# Base search extensions (without CollectionSearchExtension to avoid duplicates) search_extensions = [ FieldsExtension(), QueryExtension(), @@ -98,8 +104,29 @@ ), ) +# Initialize extensions with just the search and aggregation extensions +# Initialize with base extensions extensions = [aggregation_extension] + search_extensions +# 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] + ), + FreeTextExtension(conformance_classes=[FreeTextConformanceClasses.COLLECTIONS]), +] + +# 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] 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..dd73384b 100644 --- a/stac_fastapi/opensearch/stac_fastapi/opensearch/app.py +++ b/stac_fastapi/opensearch/stac_fastapi/opensearch/app.py @@ -25,13 +25,19 @@ 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 ( @@ -59,7 +65,6 @@ filter_extension.conformance_classes.append( FilterConformanceClasses.ADVANCED_COMPARISON_OPERATORS ) - aggregation_extension = AggregationExtension( client=EsAsyncBaseAggregationClient( database=database_logic, session=session, settings=settings @@ -68,6 +73,7 @@ aggregation_extension.POST = EsAggregationExtensionPostRequest aggregation_extension.GET = EsAggregationExtensionGetRequest +# Base search extensions (without CollectionSearchExtension to avoid duplicates) search_extensions = [ FieldsExtension(), QueryExtension(), @@ -77,7 +83,6 @@ FreeTextExtension(), ] - if TRANSACTIONS_EXTENSIONS: search_extensions.insert( 0, @@ -99,8 +104,29 @@ ), ) +# Initialize extensions with just the search and aggregation extensions +# Initialize with base extensions extensions = [aggregation_extension] + search_extensions +# 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] + ), + FreeTextExtension(conformance_classes=[FreeTextConformanceClasses.COLLECTIONS]), +] + +# 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] post_request_model = create_post_request_model(search_extensions) 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}, 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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy