stac-fastapi-core 6.4.0__tar.gz → 6.5.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/PKG-INFO +32 -10
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/README.md +31 -9
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/core.py +227 -16
- stac_fastapi_core-6.5.1/stac_fastapi/core/extensions/__init__.py +11 -0
- stac_fastapi_core-6.5.1/stac_fastapi/core/extensions/collections_search.py +194 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/version.py +1 -1
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi_core.egg-info/PKG-INFO +32 -10
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi_core.egg-info/SOURCES.txt +1 -0
- stac_fastapi_core-6.4.0/stac_fastapi/core/extensions/__init__.py +0 -5
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/setup.cfg +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/setup.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/__init__.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/base_database_logic.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/base_settings.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/basic_auth.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/datetime_utils.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/extensions/aggregation.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/extensions/fields.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/extensions/filter.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/extensions/query.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/models/__init__.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/models/links.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/models/search.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/rate_limit.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/route_dependencies.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/serializers.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/session.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/utilities.py +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi_core.egg-info/dependency_links.txt +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi_core.egg-info/not-zip-safe +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi_core.egg-info/requires.txt +0 -0
- {stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi_core.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: stac_fastapi_core
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.5.1
|
|
4
4
|
Summary: Core library for the Elasticsearch and Opensearch stac-fastapi backends.
|
|
5
5
|
Home-page: https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch
|
|
6
6
|
License: MIT
|
|
@@ -84,13 +84,13 @@ This project is built on the following technologies: STAC, stac-fastapi, FastAPI
|
|
|
84
84
|
## Table of Contents
|
|
85
85
|
|
|
86
86
|
- [stac-fastapi-elasticsearch-opensearch](#stac-fastapi-elasticsearch-opensearch)
|
|
87
|
-
- [Sponsors
|
|
87
|
+
- [Sponsors & Supporters](#sponsors--supporters)
|
|
88
88
|
- [Project Introduction - What is SFEOS?](#project-introduction---what-is-sfeos)
|
|
89
89
|
- [Common Deployment Patterns](#common-deployment-patterns)
|
|
90
90
|
- [Technologies](#technologies)
|
|
91
91
|
- [Table of Contents](#table-of-contents)
|
|
92
92
|
- [Collection Search Extensions](#collection-search-extensions)
|
|
93
|
-
- [Documentation
|
|
93
|
+
- [Documentation & Resources](#documentation--resources)
|
|
94
94
|
- [Package Structure](#package-structure)
|
|
95
95
|
- [Examples](#examples)
|
|
96
96
|
- [Performance](#performance)
|
|
@@ -133,7 +133,11 @@ This project is built on the following technologies: STAC, stac-fastapi, FastAPI
|
|
|
133
133
|
|
|
134
134
|
## Collection Search Extensions
|
|
135
135
|
|
|
136
|
-
SFEOS
|
|
136
|
+
SFEOS provides enhanced collection search capabilities through two primary routes:
|
|
137
|
+
- **GET/POST `/collections`**: The standard STAC endpoint with extended query parameters
|
|
138
|
+
- **GET/POST `/collections-search`**: A custom endpoint that supports the same parameters, created to avoid conflicts with the STAC Transactions extension if enabled (which uses POST `/collections` for collection creation)
|
|
139
|
+
|
|
140
|
+
These endpoints support advanced collection discovery features including:
|
|
137
141
|
|
|
138
142
|
- **Sorting**: Sort collections by sortable fields using the `sortby` parameter
|
|
139
143
|
- Example: `/collections?sortby=+id` (ascending sort by ID)
|
|
@@ -149,9 +153,26 @@ SFEOS implements extended capabilities for the `/collections` endpoint, allowing
|
|
|
149
153
|
- Searches across multiple text fields including title, description, and keywords
|
|
150
154
|
- Supports partial word matching and relevance-based sorting
|
|
151
155
|
|
|
156
|
+
- **Structured Filtering**: Filter collections using CQL2 expressions
|
|
157
|
+
- JSON format: `/collections?filter={"op":"=","args":[{"property":"id"},"sentinel-2"]}&filter-lang=cql2-json`
|
|
158
|
+
- Text format: `/collections?filter=id='sentinel-2'&filter-lang=cql2-text` (note: string values must be quoted)
|
|
159
|
+
- Advanced text format: `/collections?filter=id LIKE '%sentinel%'&filter-lang=cql2-text` (supports LIKE, BETWEEN, etc.)
|
|
160
|
+
- Supports both CQL2 JSON and CQL2 text formats with various operators
|
|
161
|
+
- Enables precise filtering on any collection property
|
|
162
|
+
|
|
163
|
+
- **Datetime Filtering**: Filter collections by their temporal extent using the `datetime` parameter
|
|
164
|
+
- Example: `/collections?datetime=2020-01-01T00:00:00Z/2020-12-31T23:59:59Z` (finds collections with temporal extents that overlap this range)
|
|
165
|
+
- Example: `/collections?datetime=2020-06-15T12:00:00Z` (finds collections whose temporal extent includes this specific time)
|
|
166
|
+
- Example: `/collections?datetime=2020-01-01T00:00:00Z/..` (finds collections with temporal extents that extend to or beyond January 1, 2020)
|
|
167
|
+
- Example: `/collections?datetime=../2020-12-31T23:59:59Z` (finds collections with temporal extents that begin on or before December 31, 2020)
|
|
168
|
+
- Collections are matched if their temporal extent overlaps with the provided datetime parameter
|
|
169
|
+
- This allows for efficient discovery of collections based on time periods
|
|
170
|
+
|
|
152
171
|
These extensions make it easier to build user interfaces that display and navigate through collections efficiently.
|
|
153
172
|
|
|
154
|
-
> **Configuration**: Collection search extensions can be disabled by setting the `ENABLE_COLLECTIONS_SEARCH` environment variable to `false`. By default, these extensions are enabled.
|
|
173
|
+
> **Configuration**: Collection search extensions (sorting, field selection, free text search, structured filtering, and datetime filtering) for the `/collections` endpoint can be disabled by setting the `ENABLE_COLLECTIONS_SEARCH` environment variable to `false`. By default, these extensions are enabled.
|
|
174
|
+
>
|
|
175
|
+
> **Configuration**: The custom `/collections-search` endpoint can be enabled by setting the `ENABLE_COLLECTIONS_SEARCH_ROUTE` environment variable to `true`. By default, this endpoint is **disabled**.
|
|
155
176
|
|
|
156
177
|
> **Note**: Sorting is only available on fields that are indexed for sorting in Elasticsearch/OpenSearch. With the default mappings, you can sort on:
|
|
157
178
|
> - `id` (keyword field)
|
|
@@ -162,6 +183,7 @@ These extensions make it easier to build user interfaces that display and naviga
|
|
|
162
183
|
>
|
|
163
184
|
> **Important**: Adding keyword fields to make text fields sortable can significantly increase the index size, especially for large text fields. Consider the storage implications when deciding which fields to make sortable.
|
|
164
185
|
|
|
186
|
+
|
|
165
187
|
## Package Structure
|
|
166
188
|
|
|
167
189
|
This project is organized into several packages, each with a specific purpose:
|
|
@@ -174,7 +196,7 @@ This project is organized into several packages, each with a specific purpose:
|
|
|
174
196
|
- Shared logic and utilities that improve code reuse between backends
|
|
175
197
|
|
|
176
198
|
- **stac_fastapi_elasticsearch**: Complete implementation of the STAC API using Elasticsearch as the backend database. This package depends on both `stac_fastapi_core` and `sfeos_helpers`.
|
|
177
|
-
|
|
199
|
+
|
|
178
200
|
- **stac_fastapi_opensearch**: Complete implementation of the STAC API using OpenSearch as the backend database. This package depends on both `stac_fastapi_core` and `sfeos_helpers`.
|
|
179
201
|
|
|
180
202
|
## Examples
|
|
@@ -292,12 +314,13 @@ You can customize additional settings in your `.env` file:
|
|
|
292
314
|
| `ENABLE_DIRECT_RESPONSE` | Enable direct response for maximum performance (disables all FastAPI dependencies, including authentication, custom status codes, and validation) | `false` | Optional |
|
|
293
315
|
| `RAISE_ON_BULK_ERROR` | Controls whether bulk insert operations raise exceptions on errors. If set to `true`, the operation will stop and raise an exception when an error occurs. If set to `false`, errors will be logged, and the operation will continue. **Note:** STAC Item and ItemCollection validation errors will always raise, regardless of this flag. | `false` | Optional |
|
|
294
316
|
| `DATABASE_REFRESH` | Controls whether database operations refresh the index immediately after changes. If set to `true`, changes will be immediately searchable. If set to `false`, changes may not be immediately visible but can improve performance for bulk operations. If set to `wait_for`, changes will wait for the next refresh cycle to become visible. | `false` | Optional |
|
|
295
|
-
| `ENABLE_COLLECTIONS_SEARCH` | Enable collection search extensions (sort, fields).
|
|
296
|
-
| `
|
|
317
|
+
| `ENABLE_COLLECTIONS_SEARCH` | Enable collection search extensions (sort, fields, free text search, structured filtering, and datetime filtering) on the core `/collections` endpoint. | `true` | Optional |
|
|
318
|
+
| `ENABLE_COLLECTIONS_SEARCH_ROUTE` | Enable the custom `/collections-search` endpoint (both GET and POST methods). When disabled, the custom endpoint will not be available, but collection search extensions will still be available on the core `/collections` endpoint if `ENABLE_COLLECTIONS_SEARCH` is true. | `false` | Optional |
|
|
319
|
+
| `ENABLE_TRANSACTIONS_EXTENSIONS` | Enables or disables the Transactions and Bulk Transactions API extensions. This is useful for deployments where mutating the catalog via the API should be prevented. If set to `true`, the POST `/collections` route for search will be unavailable in the API. | `true` | Optional |
|
|
297
320
|
| `STAC_ITEM_LIMIT` | Sets the environment variable for result limiting to SFEOS for the number of returned items and STAC collections. | `10` | Optional |
|
|
298
321
|
| `STAC_INDEX_ASSETS` | Controls if Assets are indexed when added to Elasticsearch/Opensearch. This allows asset fields to be included in search queries. | `false` | Optional |
|
|
299
322
|
| `ENV_MAX_LIMIT` | Configures the environment variable in SFEOS to override the default `MAX_LIMIT`, which controls the limit parameter for returned items and STAC collections. | `10,000` | Optional |
|
|
300
|
-
| `USE_DATETIME` | Configures the datetime search behavior in SFEOS. When enabled, searches both datetime field and falls back to start_datetime/end_datetime range for items with null datetime. When disabled, searches only by start_datetime/end_datetime range. |
|
|
323
|
+
| `USE_DATETIME` | Configures the datetime search behavior in SFEOS. When enabled, searches both datetime field and falls back to start_datetime/end_datetime range for items with null datetime. When disabled, searches only by start_datetime/end_datetime range. | `true` | Optional |
|
|
301
324
|
|
|
302
325
|
> [!NOTE]
|
|
303
326
|
> The variables `ES_HOST`, `ES_PORT`, `ES_USE_SSL`, `ES_VERIFY_CERTS` and `ES_TIMEOUT` apply to both Elasticsearch and OpenSearch backends, so there is no need to rename the key names to `OS_` even if you're using OpenSearch.
|
|
@@ -443,7 +466,6 @@ The system uses a precise naming convention:
|
|
|
443
466
|
- `ENABLE_COLLECTIONS_SEARCH`: Set to `true` (default) to enable collection search extensions (sort, fields). Set to `false` to disable.
|
|
444
467
|
- `ENABLE_TRANSACTIONS_EXTENSIONS`: Set to `true` (default) to enable transaction extensions. Set to `false` to disable.
|
|
445
468
|
|
|
446
|
-
|
|
447
469
|
## Collection Pagination
|
|
448
470
|
|
|
449
471
|
- **Overview**: The collections route supports pagination through optional query parameters.
|
|
@@ -66,13 +66,13 @@ This project is built on the following technologies: STAC, stac-fastapi, FastAPI
|
|
|
66
66
|
## Table of Contents
|
|
67
67
|
|
|
68
68
|
- [stac-fastapi-elasticsearch-opensearch](#stac-fastapi-elasticsearch-opensearch)
|
|
69
|
-
- [Sponsors
|
|
69
|
+
- [Sponsors & Supporters](#sponsors--supporters)
|
|
70
70
|
- [Project Introduction - What is SFEOS?](#project-introduction---what-is-sfeos)
|
|
71
71
|
- [Common Deployment Patterns](#common-deployment-patterns)
|
|
72
72
|
- [Technologies](#technologies)
|
|
73
73
|
- [Table of Contents](#table-of-contents)
|
|
74
74
|
- [Collection Search Extensions](#collection-search-extensions)
|
|
75
|
-
- [Documentation
|
|
75
|
+
- [Documentation & Resources](#documentation--resources)
|
|
76
76
|
- [Package Structure](#package-structure)
|
|
77
77
|
- [Examples](#examples)
|
|
78
78
|
- [Performance](#performance)
|
|
@@ -115,7 +115,11 @@ This project is built on the following technologies: STAC, stac-fastapi, FastAPI
|
|
|
115
115
|
|
|
116
116
|
## Collection Search Extensions
|
|
117
117
|
|
|
118
|
-
SFEOS
|
|
118
|
+
SFEOS provides enhanced collection search capabilities through two primary routes:
|
|
119
|
+
- **GET/POST `/collections`**: The standard STAC endpoint with extended query parameters
|
|
120
|
+
- **GET/POST `/collections-search`**: A custom endpoint that supports the same parameters, created to avoid conflicts with the STAC Transactions extension if enabled (which uses POST `/collections` for collection creation)
|
|
121
|
+
|
|
122
|
+
These endpoints support advanced collection discovery features including:
|
|
119
123
|
|
|
120
124
|
- **Sorting**: Sort collections by sortable fields using the `sortby` parameter
|
|
121
125
|
- Example: `/collections?sortby=+id` (ascending sort by ID)
|
|
@@ -131,9 +135,26 @@ SFEOS implements extended capabilities for the `/collections` endpoint, allowing
|
|
|
131
135
|
- Searches across multiple text fields including title, description, and keywords
|
|
132
136
|
- Supports partial word matching and relevance-based sorting
|
|
133
137
|
|
|
138
|
+
- **Structured Filtering**: Filter collections using CQL2 expressions
|
|
139
|
+
- JSON format: `/collections?filter={"op":"=","args":[{"property":"id"},"sentinel-2"]}&filter-lang=cql2-json`
|
|
140
|
+
- Text format: `/collections?filter=id='sentinel-2'&filter-lang=cql2-text` (note: string values must be quoted)
|
|
141
|
+
- Advanced text format: `/collections?filter=id LIKE '%sentinel%'&filter-lang=cql2-text` (supports LIKE, BETWEEN, etc.)
|
|
142
|
+
- Supports both CQL2 JSON and CQL2 text formats with various operators
|
|
143
|
+
- Enables precise filtering on any collection property
|
|
144
|
+
|
|
145
|
+
- **Datetime Filtering**: Filter collections by their temporal extent using the `datetime` parameter
|
|
146
|
+
- Example: `/collections?datetime=2020-01-01T00:00:00Z/2020-12-31T23:59:59Z` (finds collections with temporal extents that overlap this range)
|
|
147
|
+
- Example: `/collections?datetime=2020-06-15T12:00:00Z` (finds collections whose temporal extent includes this specific time)
|
|
148
|
+
- Example: `/collections?datetime=2020-01-01T00:00:00Z/..` (finds collections with temporal extents that extend to or beyond January 1, 2020)
|
|
149
|
+
- Example: `/collections?datetime=../2020-12-31T23:59:59Z` (finds collections with temporal extents that begin on or before December 31, 2020)
|
|
150
|
+
- Collections are matched if their temporal extent overlaps with the provided datetime parameter
|
|
151
|
+
- This allows for efficient discovery of collections based on time periods
|
|
152
|
+
|
|
134
153
|
These extensions make it easier to build user interfaces that display and navigate through collections efficiently.
|
|
135
154
|
|
|
136
|
-
> **Configuration**: Collection search extensions can be disabled by setting the `ENABLE_COLLECTIONS_SEARCH` environment variable to `false`. By default, these extensions are enabled.
|
|
155
|
+
> **Configuration**: Collection search extensions (sorting, field selection, free text search, structured filtering, and datetime filtering) for the `/collections` endpoint can be disabled by setting the `ENABLE_COLLECTIONS_SEARCH` environment variable to `false`. By default, these extensions are enabled.
|
|
156
|
+
>
|
|
157
|
+
> **Configuration**: The custom `/collections-search` endpoint can be enabled by setting the `ENABLE_COLLECTIONS_SEARCH_ROUTE` environment variable to `true`. By default, this endpoint is **disabled**.
|
|
137
158
|
|
|
138
159
|
> **Note**: Sorting is only available on fields that are indexed for sorting in Elasticsearch/OpenSearch. With the default mappings, you can sort on:
|
|
139
160
|
> - `id` (keyword field)
|
|
@@ -144,6 +165,7 @@ These extensions make it easier to build user interfaces that display and naviga
|
|
|
144
165
|
>
|
|
145
166
|
> **Important**: Adding keyword fields to make text fields sortable can significantly increase the index size, especially for large text fields. Consider the storage implications when deciding which fields to make sortable.
|
|
146
167
|
|
|
168
|
+
|
|
147
169
|
## Package Structure
|
|
148
170
|
|
|
149
171
|
This project is organized into several packages, each with a specific purpose:
|
|
@@ -156,7 +178,7 @@ This project is organized into several packages, each with a specific purpose:
|
|
|
156
178
|
- Shared logic and utilities that improve code reuse between backends
|
|
157
179
|
|
|
158
180
|
- **stac_fastapi_elasticsearch**: Complete implementation of the STAC API using Elasticsearch as the backend database. This package depends on both `stac_fastapi_core` and `sfeos_helpers`.
|
|
159
|
-
|
|
181
|
+
|
|
160
182
|
- **stac_fastapi_opensearch**: Complete implementation of the STAC API using OpenSearch as the backend database. This package depends on both `stac_fastapi_core` and `sfeos_helpers`.
|
|
161
183
|
|
|
162
184
|
## Examples
|
|
@@ -274,12 +296,13 @@ You can customize additional settings in your `.env` file:
|
|
|
274
296
|
| `ENABLE_DIRECT_RESPONSE` | Enable direct response for maximum performance (disables all FastAPI dependencies, including authentication, custom status codes, and validation) | `false` | Optional |
|
|
275
297
|
| `RAISE_ON_BULK_ERROR` | Controls whether bulk insert operations raise exceptions on errors. If set to `true`, the operation will stop and raise an exception when an error occurs. If set to `false`, errors will be logged, and the operation will continue. **Note:** STAC Item and ItemCollection validation errors will always raise, regardless of this flag. | `false` | Optional |
|
|
276
298
|
| `DATABASE_REFRESH` | Controls whether database operations refresh the index immediately after changes. If set to `true`, changes will be immediately searchable. If set to `false`, changes may not be immediately visible but can improve performance for bulk operations. If set to `wait_for`, changes will wait for the next refresh cycle to become visible. | `false` | Optional |
|
|
277
|
-
| `ENABLE_COLLECTIONS_SEARCH` | Enable collection search extensions (sort, fields).
|
|
278
|
-
| `
|
|
299
|
+
| `ENABLE_COLLECTIONS_SEARCH` | Enable collection search extensions (sort, fields, free text search, structured filtering, and datetime filtering) on the core `/collections` endpoint. | `true` | Optional |
|
|
300
|
+
| `ENABLE_COLLECTIONS_SEARCH_ROUTE` | Enable the custom `/collections-search` endpoint (both GET and POST methods). When disabled, the custom endpoint will not be available, but collection search extensions will still be available on the core `/collections` endpoint if `ENABLE_COLLECTIONS_SEARCH` is true. | `false` | Optional |
|
|
301
|
+
| `ENABLE_TRANSACTIONS_EXTENSIONS` | Enables or disables the Transactions and Bulk Transactions API extensions. This is useful for deployments where mutating the catalog via the API should be prevented. If set to `true`, the POST `/collections` route for search will be unavailable in the API. | `true` | Optional |
|
|
279
302
|
| `STAC_ITEM_LIMIT` | Sets the environment variable for result limiting to SFEOS for the number of returned items and STAC collections. | `10` | Optional |
|
|
280
303
|
| `STAC_INDEX_ASSETS` | Controls if Assets are indexed when added to Elasticsearch/Opensearch. This allows asset fields to be included in search queries. | `false` | Optional |
|
|
281
304
|
| `ENV_MAX_LIMIT` | Configures the environment variable in SFEOS to override the default `MAX_LIMIT`, which controls the limit parameter for returned items and STAC collections. | `10,000` | Optional |
|
|
282
|
-
| `USE_DATETIME` | Configures the datetime search behavior in SFEOS. When enabled, searches both datetime field and falls back to start_datetime/end_datetime range for items with null datetime. When disabled, searches only by start_datetime/end_datetime range. |
|
|
305
|
+
| `USE_DATETIME` | Configures the datetime search behavior in SFEOS. When enabled, searches both datetime field and falls back to start_datetime/end_datetime range for items with null datetime. When disabled, searches only by start_datetime/end_datetime range. | `true` | Optional |
|
|
283
306
|
|
|
284
307
|
> [!NOTE]
|
|
285
308
|
> The variables `ES_HOST`, `ES_PORT`, `ES_USE_SSL`, `ES_VERIFY_CERTS` and `ES_TIMEOUT` apply to both Elasticsearch and OpenSearch backends, so there is no need to rename the key names to `OS_` even if you're using OpenSearch.
|
|
@@ -425,7 +448,6 @@ The system uses a precise naming convention:
|
|
|
425
448
|
- `ENABLE_COLLECTIONS_SEARCH`: Set to `true` (default) to enable collection search extensions (sort, fields). Set to `false` to disable.
|
|
426
449
|
- `ENABLE_TRANSACTIONS_EXTENSIONS`: Set to `true` (default) to enable transaction extensions. Set to `false` to disable.
|
|
427
450
|
|
|
428
|
-
|
|
429
451
|
## Collection Pagination
|
|
430
452
|
|
|
431
453
|
- **Overview**: The collections route supports pagination through optional query parameters.
|
|
@@ -136,6 +136,20 @@ class CoreClient(AsyncBaseCoreClient):
|
|
|
136
136
|
"href": urljoin(base_url, "search"),
|
|
137
137
|
"method": "POST",
|
|
138
138
|
},
|
|
139
|
+
{
|
|
140
|
+
"rel": "collections-search",
|
|
141
|
+
"type": "application/json",
|
|
142
|
+
"title": "Collections Search",
|
|
143
|
+
"href": urljoin(base_url, "collections-search"),
|
|
144
|
+
"method": "GET",
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"rel": "collections-search",
|
|
148
|
+
"type": "application/json",
|
|
149
|
+
"title": "Collections Search",
|
|
150
|
+
"href": urljoin(base_url, "collections-search"),
|
|
151
|
+
"method": "POST",
|
|
152
|
+
},
|
|
139
153
|
],
|
|
140
154
|
stac_extensions=extension_schemas,
|
|
141
155
|
)
|
|
@@ -226,35 +240,78 @@ class CoreClient(AsyncBaseCoreClient):
|
|
|
226
240
|
|
|
227
241
|
async def all_collections(
|
|
228
242
|
self,
|
|
243
|
+
limit: Optional[int] = None,
|
|
244
|
+
datetime: Optional[str] = None,
|
|
229
245
|
fields: Optional[List[str]] = None,
|
|
230
|
-
sortby: Optional[str] = None,
|
|
246
|
+
sortby: Optional[Union[str, List[str]]] = None,
|
|
247
|
+
filter_expr: Optional[str] = None,
|
|
248
|
+
filter_lang: Optional[str] = None,
|
|
231
249
|
q: Optional[Union[str, List[str]]] = None,
|
|
250
|
+
query: Optional[str] = None,
|
|
251
|
+
request: Request = None,
|
|
252
|
+
token: Optional[str] = None,
|
|
232
253
|
**kwargs,
|
|
233
254
|
) -> stac_types.Collections:
|
|
234
255
|
"""Read all collections from the database.
|
|
235
256
|
|
|
236
257
|
Args:
|
|
258
|
+
datetime (Optional[str]): Filter collections by datetime range.
|
|
259
|
+
limit (Optional[int]): Maximum number of collections to return.
|
|
237
260
|
fields (Optional[List[str]]): Fields to include or exclude from the results.
|
|
238
261
|
sortby (Optional[str]): Sorting options for the results.
|
|
239
|
-
|
|
262
|
+
filter_expr (Optional[str]): Structured filter expression in CQL2 JSON or CQL2-text format.
|
|
263
|
+
query (Optional[str]): Legacy query parameter (deprecated).
|
|
264
|
+
filter_lang (Optional[str]): Must be 'cql2-json' or 'cql2-text' if specified, other values will result in an error.
|
|
265
|
+
q (Optional[Union[str, List[str]]]): Free text search terms.
|
|
240
266
|
**kwargs: Keyword arguments from the request.
|
|
241
267
|
|
|
242
268
|
Returns:
|
|
243
269
|
A Collections object containing all the collections in the database and links to various resources.
|
|
244
270
|
"""
|
|
245
|
-
request = kwargs["request"]
|
|
246
271
|
base_url = str(request.base_url)
|
|
247
|
-
|
|
248
|
-
|
|
272
|
+
|
|
273
|
+
# Get the global limit from environment variable
|
|
274
|
+
global_limit = None
|
|
275
|
+
env_limit = os.getenv("STAC_ITEM_LIMIT")
|
|
276
|
+
if env_limit:
|
|
277
|
+
try:
|
|
278
|
+
global_limit = int(env_limit)
|
|
279
|
+
except ValueError:
|
|
280
|
+
# Handle invalid integer in environment variable
|
|
281
|
+
pass
|
|
282
|
+
|
|
283
|
+
# Apply global limit if it exists
|
|
284
|
+
if global_limit is not None:
|
|
285
|
+
# If a limit was provided, use the smaller of the two
|
|
286
|
+
if limit is not None:
|
|
287
|
+
limit = min(limit, global_limit)
|
|
288
|
+
else:
|
|
289
|
+
limit = global_limit
|
|
290
|
+
else:
|
|
291
|
+
# No global limit, use provided limit or default
|
|
292
|
+
if limit is None:
|
|
293
|
+
query_limit = request.query_params.get("limit")
|
|
294
|
+
if query_limit:
|
|
295
|
+
try:
|
|
296
|
+
limit = int(query_limit)
|
|
297
|
+
except ValueError:
|
|
298
|
+
limit = 10
|
|
299
|
+
else:
|
|
300
|
+
limit = 10
|
|
301
|
+
|
|
302
|
+
# Get token from query params only if not already provided (for GET requests)
|
|
303
|
+
if token is None:
|
|
304
|
+
token = request.query_params.get("token")
|
|
249
305
|
|
|
250
306
|
# Process fields parameter for filtering collection properties
|
|
251
307
|
includes, excludes = set(), set()
|
|
252
|
-
if fields
|
|
308
|
+
if fields:
|
|
253
309
|
for field in fields:
|
|
254
310
|
if field[0] == "-":
|
|
255
311
|
excludes.add(field[1:])
|
|
256
312
|
else:
|
|
257
|
-
|
|
313
|
+
include_field = field[1:] if field[0] in "+ " else field
|
|
314
|
+
includes.add(include_field)
|
|
258
315
|
|
|
259
316
|
sort = None
|
|
260
317
|
if sortby:
|
|
@@ -276,12 +333,82 @@ class CoreClient(AsyncBaseCoreClient):
|
|
|
276
333
|
if q is not None:
|
|
277
334
|
q_list = [q] if isinstance(q, str) else q
|
|
278
335
|
|
|
279
|
-
|
|
280
|
-
|
|
336
|
+
# Parse the query parameter if provided
|
|
337
|
+
parsed_query = None
|
|
338
|
+
if query is not None:
|
|
339
|
+
try:
|
|
340
|
+
parsed_query = orjson.loads(query)
|
|
341
|
+
except Exception as e:
|
|
342
|
+
raise HTTPException(
|
|
343
|
+
status_code=400, detail=f"Invalid query parameter: {e}"
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
# Parse the filter parameter if provided
|
|
347
|
+
parsed_filter = None
|
|
348
|
+
if filter_expr is not None:
|
|
349
|
+
try:
|
|
350
|
+
# Only raise an error for explicitly unsupported filter languages
|
|
351
|
+
if filter_lang is not None and filter_lang not in [
|
|
352
|
+
"cql2-json",
|
|
353
|
+
"cql2-text",
|
|
354
|
+
]:
|
|
355
|
+
# Raise an error for unsupported filter languages
|
|
356
|
+
raise HTTPException(
|
|
357
|
+
status_code=400,
|
|
358
|
+
detail=f"Only 'cql2-json' and 'cql2-text' filter languages are supported for collections. Got '{filter_lang}'.",
|
|
359
|
+
)
|
|
360
|
+
|
|
361
|
+
# Handle different filter formats
|
|
362
|
+
try:
|
|
363
|
+
if filter_lang == "cql2-text" or filter_lang is None:
|
|
364
|
+
# For cql2-text or when no filter_lang is specified, try both formats
|
|
365
|
+
try:
|
|
366
|
+
# First try to parse as JSON
|
|
367
|
+
parsed_filter = orjson.loads(unquote_plus(filter_expr))
|
|
368
|
+
except Exception:
|
|
369
|
+
# If that fails, use pygeofilter to convert CQL2-text to CQL2-JSON
|
|
370
|
+
try:
|
|
371
|
+
# Parse CQL2-text and convert to CQL2-JSON
|
|
372
|
+
text_filter = unquote_plus(filter_expr)
|
|
373
|
+
parsed_ast = parse_cql2_text(text_filter)
|
|
374
|
+
parsed_filter = to_cql2(parsed_ast)
|
|
375
|
+
except Exception as e:
|
|
376
|
+
# If parsing fails, provide a helpful error message
|
|
377
|
+
raise HTTPException(
|
|
378
|
+
status_code=400,
|
|
379
|
+
detail=f"Invalid CQL2-text filter: {e}. Please check your syntax.",
|
|
380
|
+
)
|
|
381
|
+
else:
|
|
382
|
+
# For explicit cql2-json, parse as JSON
|
|
383
|
+
parsed_filter = orjson.loads(unquote_plus(filter_expr))
|
|
384
|
+
except Exception as e:
|
|
385
|
+
# Catch any other parsing errors
|
|
386
|
+
raise HTTPException(
|
|
387
|
+
status_code=400, detail=f"Error parsing filter: {e}"
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
except Exception as e:
|
|
391
|
+
raise HTTPException(
|
|
392
|
+
status_code=400, detail=f"Invalid filter parameter: {e}"
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
parsed_datetime = None
|
|
396
|
+
if datetime:
|
|
397
|
+
parsed_datetime = format_datetime_range(date_str=datetime)
|
|
398
|
+
|
|
399
|
+
collections, next_token, maybe_count = await self.database.get_all_collections(
|
|
400
|
+
token=token,
|
|
401
|
+
limit=limit,
|
|
402
|
+
request=request,
|
|
403
|
+
sort=sort,
|
|
404
|
+
q=q_list,
|
|
405
|
+
filter=parsed_filter,
|
|
406
|
+
query=parsed_query,
|
|
407
|
+
datetime=parsed_datetime,
|
|
281
408
|
)
|
|
282
409
|
|
|
283
410
|
# Apply field filtering if fields parameter was provided
|
|
284
|
-
if fields
|
|
411
|
+
if fields:
|
|
285
412
|
filtered_collections = [
|
|
286
413
|
filter_fields(collection, includes, excludes)
|
|
287
414
|
for collection in collections
|
|
@@ -303,7 +430,95 @@ class CoreClient(AsyncBaseCoreClient):
|
|
|
303
430
|
next_link = PagingLinks(next=next_token, request=request).link_next()
|
|
304
431
|
links.append(next_link)
|
|
305
432
|
|
|
306
|
-
return stac_types.Collections(
|
|
433
|
+
return stac_types.Collections(
|
|
434
|
+
collections=filtered_collections,
|
|
435
|
+
links=links,
|
|
436
|
+
numberMatched=maybe_count,
|
|
437
|
+
numberReturned=len(filtered_collections),
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
async def post_all_collections(
|
|
441
|
+
self, search_request: BaseSearchPostRequest, request: Request, **kwargs
|
|
442
|
+
) -> stac_types.Collections:
|
|
443
|
+
"""Search collections with POST request.
|
|
444
|
+
|
|
445
|
+
Args:
|
|
446
|
+
search_request (BaseSearchPostRequest): The search request.
|
|
447
|
+
request (Request): The request.
|
|
448
|
+
|
|
449
|
+
Returns:
|
|
450
|
+
A Collections object containing all the collections in the database and links to various resources.
|
|
451
|
+
"""
|
|
452
|
+
request.postbody = search_request.model_dump(exclude_unset=True)
|
|
453
|
+
|
|
454
|
+
fields = None
|
|
455
|
+
|
|
456
|
+
# Check for field attribute (ExtendedSearch format)
|
|
457
|
+
if hasattr(search_request, "field") and search_request.field:
|
|
458
|
+
fields = []
|
|
459
|
+
|
|
460
|
+
# Handle include fields
|
|
461
|
+
if (
|
|
462
|
+
hasattr(search_request.field, "includes")
|
|
463
|
+
and search_request.field.includes
|
|
464
|
+
):
|
|
465
|
+
for field in search_request.field.includes:
|
|
466
|
+
fields.append(f"+{field}")
|
|
467
|
+
|
|
468
|
+
# Handle exclude fields
|
|
469
|
+
if (
|
|
470
|
+
hasattr(search_request.field, "excludes")
|
|
471
|
+
and search_request.field.excludes
|
|
472
|
+
):
|
|
473
|
+
for field in search_request.field.excludes:
|
|
474
|
+
fields.append(f"-{field}")
|
|
475
|
+
|
|
476
|
+
# Convert sortby parameter from POST format to all_collections format
|
|
477
|
+
sortby = None
|
|
478
|
+
# Check for sortby attribute
|
|
479
|
+
if hasattr(search_request, "sortby") and search_request.sortby:
|
|
480
|
+
# Create a list of sort strings in the format expected by all_collections
|
|
481
|
+
sortby = []
|
|
482
|
+
for sort_item in search_request.sortby:
|
|
483
|
+
# Handle different types of sort items
|
|
484
|
+
if hasattr(sort_item, "field") and hasattr(sort_item, "direction"):
|
|
485
|
+
# This is a Pydantic model with field and direction attributes
|
|
486
|
+
field = sort_item.field
|
|
487
|
+
direction = sort_item.direction
|
|
488
|
+
elif isinstance(sort_item, dict):
|
|
489
|
+
# This is a dictionary with field and direction keys
|
|
490
|
+
field = sort_item.get("field")
|
|
491
|
+
direction = sort_item.get("direction", "asc")
|
|
492
|
+
else:
|
|
493
|
+
# Skip this item if we can't extract field and direction
|
|
494
|
+
continue
|
|
495
|
+
|
|
496
|
+
if field:
|
|
497
|
+
# Create a sort string in the format expected by all_collections
|
|
498
|
+
# e.g., "-id" for descending sort on id field
|
|
499
|
+
prefix = "-" if direction.lower() == "desc" else ""
|
|
500
|
+
sortby.append(f"{prefix}{field}")
|
|
501
|
+
|
|
502
|
+
# Pass all parameters from search_request to all_collections
|
|
503
|
+
return await self.all_collections(
|
|
504
|
+
limit=search_request.limit if hasattr(search_request, "limit") else None,
|
|
505
|
+
datetime=search_request.datetime
|
|
506
|
+
if hasattr(search_request, "datetime")
|
|
507
|
+
else None,
|
|
508
|
+
token=search_request.token if hasattr(search_request, "token") else None,
|
|
509
|
+
fields=fields,
|
|
510
|
+
sortby=sortby,
|
|
511
|
+
filter_expr=search_request.filter
|
|
512
|
+
if hasattr(search_request, "filter")
|
|
513
|
+
else None,
|
|
514
|
+
filter_lang=search_request.filter_lang
|
|
515
|
+
if hasattr(search_request, "filter_lang")
|
|
516
|
+
else None,
|
|
517
|
+
query=search_request.query if hasattr(search_request, "query") else None,
|
|
518
|
+
q=search_request.q if hasattr(search_request, "q") else None,
|
|
519
|
+
request=request,
|
|
520
|
+
**kwargs,
|
|
521
|
+
)
|
|
307
522
|
|
|
308
523
|
async def get_collection(
|
|
309
524
|
self, collection_id: str, **kwargs
|
|
@@ -621,11 +836,7 @@ class CoreClient(AsyncBaseCoreClient):
|
|
|
621
836
|
datetime_search=datetime_search,
|
|
622
837
|
)
|
|
623
838
|
|
|
624
|
-
fields = (
|
|
625
|
-
getattr(search_request, "fields", None)
|
|
626
|
-
if self.extension_is_enabled("FieldsExtension")
|
|
627
|
-
else None
|
|
628
|
-
)
|
|
839
|
+
fields = getattr(search_request, "fields", None)
|
|
629
840
|
include: Set[str] = fields.include if fields and fields.include else set()
|
|
630
841
|
exclude: Set[str] = fields.exclude if fields and fields.exclude else set()
|
|
631
842
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""elasticsearch extensions modifications."""
|
|
2
|
+
|
|
3
|
+
from .collections_search import CollectionsSearchEndpointExtension
|
|
4
|
+
from .query import Operator, QueryableTypes, QueryExtension
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"Operator",
|
|
8
|
+
"QueryableTypes",
|
|
9
|
+
"QueryExtension",
|
|
10
|
+
"CollectionsSearchEndpointExtension",
|
|
11
|
+
]
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""Collections search extension."""
|
|
2
|
+
|
|
3
|
+
from typing import List, Optional, Type, Union
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter, FastAPI, Request
|
|
6
|
+
from fastapi.responses import JSONResponse
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
from stac_pydantic.api.search import ExtendedSearch
|
|
9
|
+
from starlette.responses import Response
|
|
10
|
+
|
|
11
|
+
from stac_fastapi.api.models import APIRequest
|
|
12
|
+
from stac_fastapi.types.core import BaseCoreClient
|
|
13
|
+
from stac_fastapi.types.extension import ApiExtension
|
|
14
|
+
from stac_fastapi.types.stac import Collections
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CollectionsSearchRequest(ExtendedSearch):
|
|
18
|
+
"""Extended search model for collections with free text search support."""
|
|
19
|
+
|
|
20
|
+
q: Optional[Union[str, List[str]]] = None
|
|
21
|
+
token: Optional[str] = None
|
|
22
|
+
query: Optional[
|
|
23
|
+
str
|
|
24
|
+
] = None # Legacy query extension (deprecated but still supported)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class CollectionsSearchEndpointExtension(ApiExtension):
|
|
28
|
+
"""Collections search endpoint extension.
|
|
29
|
+
|
|
30
|
+
This extension adds a dedicated /collections-search endpoint for collection search operations.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
client: Optional[BaseCoreClient] = None,
|
|
36
|
+
settings: dict = None,
|
|
37
|
+
GET: Optional[Type[Union[BaseModel, APIRequest]]] = None,
|
|
38
|
+
POST: Optional[Type[Union[BaseModel, APIRequest]]] = None,
|
|
39
|
+
conformance_classes: Optional[List[str]] = None,
|
|
40
|
+
):
|
|
41
|
+
"""Initialize the extension.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
client: Optional BaseCoreClient instance to use for this extension.
|
|
45
|
+
settings: Dictionary of settings to pass to the extension.
|
|
46
|
+
GET: Optional GET request model.
|
|
47
|
+
POST: Optional POST request model.
|
|
48
|
+
conformance_classes: Optional list of conformance classes to add to the API.
|
|
49
|
+
"""
|
|
50
|
+
super().__init__()
|
|
51
|
+
self.client = client
|
|
52
|
+
self.settings = settings or {}
|
|
53
|
+
self.GET = GET
|
|
54
|
+
self.POST = POST
|
|
55
|
+
self.conformance_classes = conformance_classes or []
|
|
56
|
+
self.router = APIRouter()
|
|
57
|
+
self.create_endpoints()
|
|
58
|
+
|
|
59
|
+
def register(self, app: FastAPI) -> None:
|
|
60
|
+
"""Register the extension with a FastAPI application.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
app: target FastAPI application.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
None
|
|
67
|
+
"""
|
|
68
|
+
app.include_router(self.router)
|
|
69
|
+
|
|
70
|
+
def create_endpoints(self) -> None:
|
|
71
|
+
"""Create endpoints for the extension."""
|
|
72
|
+
if self.GET:
|
|
73
|
+
self.router.add_api_route(
|
|
74
|
+
name="Get Collections Search",
|
|
75
|
+
path="/collections-search",
|
|
76
|
+
response_model=None,
|
|
77
|
+
response_class=JSONResponse,
|
|
78
|
+
methods=["GET"],
|
|
79
|
+
endpoint=self.collections_search_get_endpoint,
|
|
80
|
+
**(self.settings if isinstance(self.settings, dict) else {}),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if self.POST:
|
|
84
|
+
self.router.add_api_route(
|
|
85
|
+
name="Post Collections Search",
|
|
86
|
+
path="/collections-search",
|
|
87
|
+
response_model=None,
|
|
88
|
+
response_class=JSONResponse,
|
|
89
|
+
methods=["POST"],
|
|
90
|
+
endpoint=self.collections_search_post_endpoint,
|
|
91
|
+
**(self.settings if isinstance(self.settings, dict) else {}),
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
async def collections_search_get_endpoint(
|
|
95
|
+
self, request: Request
|
|
96
|
+
) -> Union[Collections, Response]:
|
|
97
|
+
"""GET /collections-search endpoint.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
request: Request object.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Collections: Collections object.
|
|
104
|
+
"""
|
|
105
|
+
# Extract query parameters from the request
|
|
106
|
+
params = dict(request.query_params)
|
|
107
|
+
|
|
108
|
+
# Convert query parameters to appropriate types
|
|
109
|
+
if "limit" in params:
|
|
110
|
+
try:
|
|
111
|
+
params["limit"] = int(params["limit"])
|
|
112
|
+
except ValueError:
|
|
113
|
+
pass
|
|
114
|
+
|
|
115
|
+
# Handle fields parameter
|
|
116
|
+
if "fields" in params:
|
|
117
|
+
fields_str = params.pop("fields")
|
|
118
|
+
fields = fields_str.split(",")
|
|
119
|
+
params["fields"] = fields
|
|
120
|
+
|
|
121
|
+
# Handle sortby parameter
|
|
122
|
+
if "sortby" in params:
|
|
123
|
+
sortby_str = params.pop("sortby")
|
|
124
|
+
sortby = sortby_str.split(",")
|
|
125
|
+
params["sortby"] = sortby
|
|
126
|
+
|
|
127
|
+
collections = await self.client.all_collections(request=request, **params)
|
|
128
|
+
return collections
|
|
129
|
+
|
|
130
|
+
async def collections_search_post_endpoint(
|
|
131
|
+
self, request: Request, body: dict
|
|
132
|
+
) -> Union[Collections, Response]:
|
|
133
|
+
"""POST /collections-search endpoint.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
request: Request object.
|
|
137
|
+
body: Search request body.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
Collections: Collections object.
|
|
141
|
+
"""
|
|
142
|
+
# Convert the dict to an ExtendedSearch model
|
|
143
|
+
search_request = CollectionsSearchRequest.model_validate(body)
|
|
144
|
+
|
|
145
|
+
# Check if fields are present in the body
|
|
146
|
+
if "fields" in body:
|
|
147
|
+
# Extract fields from body and add them to search_request
|
|
148
|
+
if hasattr(search_request, "field"):
|
|
149
|
+
from stac_pydantic.api.extensions.fields import FieldsExtension
|
|
150
|
+
|
|
151
|
+
fields_data = body["fields"]
|
|
152
|
+
search_request.field = FieldsExtension(
|
|
153
|
+
includes=fields_data.get("include"),
|
|
154
|
+
excludes=fields_data.get("exclude"),
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Set the postbody on the request for pagination links
|
|
158
|
+
request.postbody = body
|
|
159
|
+
|
|
160
|
+
collections = await self.client.post_all_collections(
|
|
161
|
+
search_request=search_request, request=request
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
return collections
|
|
165
|
+
|
|
166
|
+
@classmethod
|
|
167
|
+
def from_extensions(
|
|
168
|
+
cls, extensions: List[ApiExtension]
|
|
169
|
+
) -> "CollectionsSearchEndpointExtension":
|
|
170
|
+
"""Create a CollectionsSearchEndpointExtension from a list of extensions.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
extensions: List of extensions to include in the CollectionsSearchEndpointExtension.
|
|
174
|
+
|
|
175
|
+
Returns:
|
|
176
|
+
CollectionsSearchEndpointExtension: A new CollectionsSearchEndpointExtension instance.
|
|
177
|
+
"""
|
|
178
|
+
from stac_fastapi.api.models import (
|
|
179
|
+
create_get_request_model,
|
|
180
|
+
create_post_request_model,
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
get_model = create_get_request_model(extensions)
|
|
184
|
+
post_model = create_post_request_model(extensions)
|
|
185
|
+
|
|
186
|
+
return cls(
|
|
187
|
+
GET=get_model,
|
|
188
|
+
POST=post_model,
|
|
189
|
+
conformance_classes=[
|
|
190
|
+
ext.conformance_classes
|
|
191
|
+
for ext in extensions
|
|
192
|
+
if hasattr(ext, "conformance_classes")
|
|
193
|
+
],
|
|
194
|
+
)
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""library version."""
|
|
2
|
-
__version__ = "6.
|
|
2
|
+
__version__ = "6.5.1"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: stac-fastapi-core
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.5.1
|
|
4
4
|
Summary: Core library for the Elasticsearch and Opensearch stac-fastapi backends.
|
|
5
5
|
Home-page: https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch
|
|
6
6
|
License: MIT
|
|
@@ -84,13 +84,13 @@ This project is built on the following technologies: STAC, stac-fastapi, FastAPI
|
|
|
84
84
|
## Table of Contents
|
|
85
85
|
|
|
86
86
|
- [stac-fastapi-elasticsearch-opensearch](#stac-fastapi-elasticsearch-opensearch)
|
|
87
|
-
- [Sponsors
|
|
87
|
+
- [Sponsors & Supporters](#sponsors--supporters)
|
|
88
88
|
- [Project Introduction - What is SFEOS?](#project-introduction---what-is-sfeos)
|
|
89
89
|
- [Common Deployment Patterns](#common-deployment-patterns)
|
|
90
90
|
- [Technologies](#technologies)
|
|
91
91
|
- [Table of Contents](#table-of-contents)
|
|
92
92
|
- [Collection Search Extensions](#collection-search-extensions)
|
|
93
|
-
- [Documentation
|
|
93
|
+
- [Documentation & Resources](#documentation--resources)
|
|
94
94
|
- [Package Structure](#package-structure)
|
|
95
95
|
- [Examples](#examples)
|
|
96
96
|
- [Performance](#performance)
|
|
@@ -133,7 +133,11 @@ This project is built on the following technologies: STAC, stac-fastapi, FastAPI
|
|
|
133
133
|
|
|
134
134
|
## Collection Search Extensions
|
|
135
135
|
|
|
136
|
-
SFEOS
|
|
136
|
+
SFEOS provides enhanced collection search capabilities through two primary routes:
|
|
137
|
+
- **GET/POST `/collections`**: The standard STAC endpoint with extended query parameters
|
|
138
|
+
- **GET/POST `/collections-search`**: A custom endpoint that supports the same parameters, created to avoid conflicts with the STAC Transactions extension if enabled (which uses POST `/collections` for collection creation)
|
|
139
|
+
|
|
140
|
+
These endpoints support advanced collection discovery features including:
|
|
137
141
|
|
|
138
142
|
- **Sorting**: Sort collections by sortable fields using the `sortby` parameter
|
|
139
143
|
- Example: `/collections?sortby=+id` (ascending sort by ID)
|
|
@@ -149,9 +153,26 @@ SFEOS implements extended capabilities for the `/collections` endpoint, allowing
|
|
|
149
153
|
- Searches across multiple text fields including title, description, and keywords
|
|
150
154
|
- Supports partial word matching and relevance-based sorting
|
|
151
155
|
|
|
156
|
+
- **Structured Filtering**: Filter collections using CQL2 expressions
|
|
157
|
+
- JSON format: `/collections?filter={"op":"=","args":[{"property":"id"},"sentinel-2"]}&filter-lang=cql2-json`
|
|
158
|
+
- Text format: `/collections?filter=id='sentinel-2'&filter-lang=cql2-text` (note: string values must be quoted)
|
|
159
|
+
- Advanced text format: `/collections?filter=id LIKE '%sentinel%'&filter-lang=cql2-text` (supports LIKE, BETWEEN, etc.)
|
|
160
|
+
- Supports both CQL2 JSON and CQL2 text formats with various operators
|
|
161
|
+
- Enables precise filtering on any collection property
|
|
162
|
+
|
|
163
|
+
- **Datetime Filtering**: Filter collections by their temporal extent using the `datetime` parameter
|
|
164
|
+
- Example: `/collections?datetime=2020-01-01T00:00:00Z/2020-12-31T23:59:59Z` (finds collections with temporal extents that overlap this range)
|
|
165
|
+
- Example: `/collections?datetime=2020-06-15T12:00:00Z` (finds collections whose temporal extent includes this specific time)
|
|
166
|
+
- Example: `/collections?datetime=2020-01-01T00:00:00Z/..` (finds collections with temporal extents that extend to or beyond January 1, 2020)
|
|
167
|
+
- Example: `/collections?datetime=../2020-12-31T23:59:59Z` (finds collections with temporal extents that begin on or before December 31, 2020)
|
|
168
|
+
- Collections are matched if their temporal extent overlaps with the provided datetime parameter
|
|
169
|
+
- This allows for efficient discovery of collections based on time periods
|
|
170
|
+
|
|
152
171
|
These extensions make it easier to build user interfaces that display and navigate through collections efficiently.
|
|
153
172
|
|
|
154
|
-
> **Configuration**: Collection search extensions can be disabled by setting the `ENABLE_COLLECTIONS_SEARCH` environment variable to `false`. By default, these extensions are enabled.
|
|
173
|
+
> **Configuration**: Collection search extensions (sorting, field selection, free text search, structured filtering, and datetime filtering) for the `/collections` endpoint can be disabled by setting the `ENABLE_COLLECTIONS_SEARCH` environment variable to `false`. By default, these extensions are enabled.
|
|
174
|
+
>
|
|
175
|
+
> **Configuration**: The custom `/collections-search` endpoint can be enabled by setting the `ENABLE_COLLECTIONS_SEARCH_ROUTE` environment variable to `true`. By default, this endpoint is **disabled**.
|
|
155
176
|
|
|
156
177
|
> **Note**: Sorting is only available on fields that are indexed for sorting in Elasticsearch/OpenSearch. With the default mappings, you can sort on:
|
|
157
178
|
> - `id` (keyword field)
|
|
@@ -162,6 +183,7 @@ These extensions make it easier to build user interfaces that display and naviga
|
|
|
162
183
|
>
|
|
163
184
|
> **Important**: Adding keyword fields to make text fields sortable can significantly increase the index size, especially for large text fields. Consider the storage implications when deciding which fields to make sortable.
|
|
164
185
|
|
|
186
|
+
|
|
165
187
|
## Package Structure
|
|
166
188
|
|
|
167
189
|
This project is organized into several packages, each with a specific purpose:
|
|
@@ -174,7 +196,7 @@ This project is organized into several packages, each with a specific purpose:
|
|
|
174
196
|
- Shared logic and utilities that improve code reuse between backends
|
|
175
197
|
|
|
176
198
|
- **stac_fastapi_elasticsearch**: Complete implementation of the STAC API using Elasticsearch as the backend database. This package depends on both `stac_fastapi_core` and `sfeos_helpers`.
|
|
177
|
-
|
|
199
|
+
|
|
178
200
|
- **stac_fastapi_opensearch**: Complete implementation of the STAC API using OpenSearch as the backend database. This package depends on both `stac_fastapi_core` and `sfeos_helpers`.
|
|
179
201
|
|
|
180
202
|
## Examples
|
|
@@ -292,12 +314,13 @@ You can customize additional settings in your `.env` file:
|
|
|
292
314
|
| `ENABLE_DIRECT_RESPONSE` | Enable direct response for maximum performance (disables all FastAPI dependencies, including authentication, custom status codes, and validation) | `false` | Optional |
|
|
293
315
|
| `RAISE_ON_BULK_ERROR` | Controls whether bulk insert operations raise exceptions on errors. If set to `true`, the operation will stop and raise an exception when an error occurs. If set to `false`, errors will be logged, and the operation will continue. **Note:** STAC Item and ItemCollection validation errors will always raise, regardless of this flag. | `false` | Optional |
|
|
294
316
|
| `DATABASE_REFRESH` | Controls whether database operations refresh the index immediately after changes. If set to `true`, changes will be immediately searchable. If set to `false`, changes may not be immediately visible but can improve performance for bulk operations. If set to `wait_for`, changes will wait for the next refresh cycle to become visible. | `false` | Optional |
|
|
295
|
-
| `ENABLE_COLLECTIONS_SEARCH` | Enable collection search extensions (sort, fields).
|
|
296
|
-
| `
|
|
317
|
+
| `ENABLE_COLLECTIONS_SEARCH` | Enable collection search extensions (sort, fields, free text search, structured filtering, and datetime filtering) on the core `/collections` endpoint. | `true` | Optional |
|
|
318
|
+
| `ENABLE_COLLECTIONS_SEARCH_ROUTE` | Enable the custom `/collections-search` endpoint (both GET and POST methods). When disabled, the custom endpoint will not be available, but collection search extensions will still be available on the core `/collections` endpoint if `ENABLE_COLLECTIONS_SEARCH` is true. | `false` | Optional |
|
|
319
|
+
| `ENABLE_TRANSACTIONS_EXTENSIONS` | Enables or disables the Transactions and Bulk Transactions API extensions. This is useful for deployments where mutating the catalog via the API should be prevented. If set to `true`, the POST `/collections` route for search will be unavailable in the API. | `true` | Optional |
|
|
297
320
|
| `STAC_ITEM_LIMIT` | Sets the environment variable for result limiting to SFEOS for the number of returned items and STAC collections. | `10` | Optional |
|
|
298
321
|
| `STAC_INDEX_ASSETS` | Controls if Assets are indexed when added to Elasticsearch/Opensearch. This allows asset fields to be included in search queries. | `false` | Optional |
|
|
299
322
|
| `ENV_MAX_LIMIT` | Configures the environment variable in SFEOS to override the default `MAX_LIMIT`, which controls the limit parameter for returned items and STAC collections. | `10,000` | Optional |
|
|
300
|
-
| `USE_DATETIME` | Configures the datetime search behavior in SFEOS. When enabled, searches both datetime field and falls back to start_datetime/end_datetime range for items with null datetime. When disabled, searches only by start_datetime/end_datetime range. |
|
|
323
|
+
| `USE_DATETIME` | Configures the datetime search behavior in SFEOS. When enabled, searches both datetime field and falls back to start_datetime/end_datetime range for items with null datetime. When disabled, searches only by start_datetime/end_datetime range. | `true` | Optional |
|
|
301
324
|
|
|
302
325
|
> [!NOTE]
|
|
303
326
|
> The variables `ES_HOST`, `ES_PORT`, `ES_USE_SSL`, `ES_VERIFY_CERTS` and `ES_TIMEOUT` apply to both Elasticsearch and OpenSearch backends, so there is no need to rename the key names to `OS_` even if you're using OpenSearch.
|
|
@@ -443,7 +466,6 @@ The system uses a precise naming convention:
|
|
|
443
466
|
- `ENABLE_COLLECTIONS_SEARCH`: Set to `true` (default) to enable collection search extensions (sort, fields). Set to `false` to disable.
|
|
444
467
|
- `ENABLE_TRANSACTIONS_EXTENSIONS`: Set to `true` (default) to enable transaction extensions. Set to `false` to disable.
|
|
445
468
|
|
|
446
|
-
|
|
447
469
|
## Collection Pagination
|
|
448
470
|
|
|
449
471
|
- **Overview**: The collections route supports pagination through optional query parameters.
|
|
@@ -15,6 +15,7 @@ stac_fastapi/core/utilities.py
|
|
|
15
15
|
stac_fastapi/core/version.py
|
|
16
16
|
stac_fastapi/core/extensions/__init__.py
|
|
17
17
|
stac_fastapi/core/extensions/aggregation.py
|
|
18
|
+
stac_fastapi/core/extensions/collections_search.py
|
|
18
19
|
stac_fastapi/core/extensions/fields.py
|
|
19
20
|
stac_fastapi/core/extensions/filter.py
|
|
20
21
|
stac_fastapi/core/extensions/query.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/base_database_logic.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi/core/extensions/aggregation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi_core.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{stac_fastapi_core-6.4.0 → stac_fastapi_core-6.5.1}/stac_fastapi_core.egg-info/top_level.txt
RENAMED
|
File without changes
|