stac-fastapi-opensearch 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_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/PKG-INFO +32 -10
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/README.md +31 -9
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/setup.py +2 -2
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi/opensearch/app.py +74 -9
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi/opensearch/database_logic.py +173 -19
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi/opensearch/version.py +1 -1
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi_opensearch.egg-info/PKG-INFO +32 -10
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi_opensearch.egg-info/requires.txt +2 -2
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/setup.cfg +0 -0
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi/opensearch/__init__.py +0 -0
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi/opensearch/config.py +0 -0
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi_opensearch.egg-info/SOURCES.txt +0 -0
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi_opensearch.egg-info/dependency_links.txt +0 -0
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi_opensearch.egg-info/entry_points.txt +0 -0
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi_opensearch.egg-info/not-zip-safe +0 -0
- {stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi_opensearch.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: stac_fastapi_opensearch
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.5.1
|
|
4
4
|
Summary: Opensearch stac-fastapi backend.
|
|
5
5
|
Home-page: https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch
|
|
6
6
|
License: MIT
|
|
@@ -87,13 +87,13 @@ This project is built on the following technologies: STAC, stac-fastapi, FastAPI
|
|
|
87
87
|
## Table of Contents
|
|
88
88
|
|
|
89
89
|
- [stac-fastapi-elasticsearch-opensearch](#stac-fastapi-elasticsearch-opensearch)
|
|
90
|
-
- [Sponsors
|
|
90
|
+
- [Sponsors & Supporters](#sponsors--supporters)
|
|
91
91
|
- [Project Introduction - What is SFEOS?](#project-introduction---what-is-sfeos)
|
|
92
92
|
- [Common Deployment Patterns](#common-deployment-patterns)
|
|
93
93
|
- [Technologies](#technologies)
|
|
94
94
|
- [Table of Contents](#table-of-contents)
|
|
95
95
|
- [Collection Search Extensions](#collection-search-extensions)
|
|
96
|
-
- [Documentation
|
|
96
|
+
- [Documentation & Resources](#documentation--resources)
|
|
97
97
|
- [Package Structure](#package-structure)
|
|
98
98
|
- [Examples](#examples)
|
|
99
99
|
- [Performance](#performance)
|
|
@@ -136,7 +136,11 @@ This project is built on the following technologies: STAC, stac-fastapi, FastAPI
|
|
|
136
136
|
|
|
137
137
|
## Collection Search Extensions
|
|
138
138
|
|
|
139
|
-
SFEOS
|
|
139
|
+
SFEOS provides enhanced collection search capabilities through two primary routes:
|
|
140
|
+
- **GET/POST `/collections`**: The standard STAC endpoint with extended query parameters
|
|
141
|
+
- **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)
|
|
142
|
+
|
|
143
|
+
These endpoints support advanced collection discovery features including:
|
|
140
144
|
|
|
141
145
|
- **Sorting**: Sort collections by sortable fields using the `sortby` parameter
|
|
142
146
|
- Example: `/collections?sortby=+id` (ascending sort by ID)
|
|
@@ -152,9 +156,26 @@ SFEOS implements extended capabilities for the `/collections` endpoint, allowing
|
|
|
152
156
|
- Searches across multiple text fields including title, description, and keywords
|
|
153
157
|
- Supports partial word matching and relevance-based sorting
|
|
154
158
|
|
|
159
|
+
- **Structured Filtering**: Filter collections using CQL2 expressions
|
|
160
|
+
- JSON format: `/collections?filter={"op":"=","args":[{"property":"id"},"sentinel-2"]}&filter-lang=cql2-json`
|
|
161
|
+
- Text format: `/collections?filter=id='sentinel-2'&filter-lang=cql2-text` (note: string values must be quoted)
|
|
162
|
+
- Advanced text format: `/collections?filter=id LIKE '%sentinel%'&filter-lang=cql2-text` (supports LIKE, BETWEEN, etc.)
|
|
163
|
+
- Supports both CQL2 JSON and CQL2 text formats with various operators
|
|
164
|
+
- Enables precise filtering on any collection property
|
|
165
|
+
|
|
166
|
+
- **Datetime Filtering**: Filter collections by their temporal extent using the `datetime` parameter
|
|
167
|
+
- Example: `/collections?datetime=2020-01-01T00:00:00Z/2020-12-31T23:59:59Z` (finds collections with temporal extents that overlap this range)
|
|
168
|
+
- Example: `/collections?datetime=2020-06-15T12:00:00Z` (finds collections whose temporal extent includes this specific time)
|
|
169
|
+
- Example: `/collections?datetime=2020-01-01T00:00:00Z/..` (finds collections with temporal extents that extend to or beyond January 1, 2020)
|
|
170
|
+
- Example: `/collections?datetime=../2020-12-31T23:59:59Z` (finds collections with temporal extents that begin on or before December 31, 2020)
|
|
171
|
+
- Collections are matched if their temporal extent overlaps with the provided datetime parameter
|
|
172
|
+
- This allows for efficient discovery of collections based on time periods
|
|
173
|
+
|
|
155
174
|
These extensions make it easier to build user interfaces that display and navigate through collections efficiently.
|
|
156
175
|
|
|
157
|
-
> **Configuration**: Collection search extensions can be disabled by setting the `ENABLE_COLLECTIONS_SEARCH` environment variable to `false`. By default, these extensions are enabled.
|
|
176
|
+
> **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.
|
|
177
|
+
>
|
|
178
|
+
> **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**.
|
|
158
179
|
|
|
159
180
|
> **Note**: Sorting is only available on fields that are indexed for sorting in Elasticsearch/OpenSearch. With the default mappings, you can sort on:
|
|
160
181
|
> - `id` (keyword field)
|
|
@@ -165,6 +186,7 @@ These extensions make it easier to build user interfaces that display and naviga
|
|
|
165
186
|
>
|
|
166
187
|
> **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.
|
|
167
188
|
|
|
189
|
+
|
|
168
190
|
## Package Structure
|
|
169
191
|
|
|
170
192
|
This project is organized into several packages, each with a specific purpose:
|
|
@@ -177,7 +199,7 @@ This project is organized into several packages, each with a specific purpose:
|
|
|
177
199
|
- Shared logic and utilities that improve code reuse between backends
|
|
178
200
|
|
|
179
201
|
- **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`.
|
|
180
|
-
|
|
202
|
+
|
|
181
203
|
- **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`.
|
|
182
204
|
|
|
183
205
|
## Examples
|
|
@@ -295,12 +317,13 @@ You can customize additional settings in your `.env` file:
|
|
|
295
317
|
| `ENABLE_DIRECT_RESPONSE` | Enable direct response for maximum performance (disables all FastAPI dependencies, including authentication, custom status codes, and validation) | `false` | Optional |
|
|
296
318
|
| `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 |
|
|
297
319
|
| `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 |
|
|
298
|
-
| `ENABLE_COLLECTIONS_SEARCH` | Enable collection search extensions (sort, fields).
|
|
299
|
-
| `
|
|
320
|
+
| `ENABLE_COLLECTIONS_SEARCH` | Enable collection search extensions (sort, fields, free text search, structured filtering, and datetime filtering) on the core `/collections` endpoint. | `true` | Optional |
|
|
321
|
+
| `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 |
|
|
322
|
+
| `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 |
|
|
300
323
|
| `STAC_ITEM_LIMIT` | Sets the environment variable for result limiting to SFEOS for the number of returned items and STAC collections. | `10` | Optional |
|
|
301
324
|
| `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 |
|
|
302
325
|
| `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 |
|
|
303
|
-
| `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. |
|
|
326
|
+
| `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 |
|
|
304
327
|
|
|
305
328
|
> [!NOTE]
|
|
306
329
|
> 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.
|
|
@@ -446,7 +469,6 @@ The system uses a precise naming convention:
|
|
|
446
469
|
- `ENABLE_COLLECTIONS_SEARCH`: Set to `true` (default) to enable collection search extensions (sort, fields). Set to `false` to disable.
|
|
447
470
|
- `ENABLE_TRANSACTIONS_EXTENSIONS`: Set to `true` (default) to enable transaction extensions. Set to `false` to disable.
|
|
448
471
|
|
|
449
|
-
|
|
450
472
|
## Collection Pagination
|
|
451
473
|
|
|
452
474
|
- **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.
|
|
@@ -6,8 +6,8 @@ with open("README.md") as f:
|
|
|
6
6
|
desc = f.read()
|
|
7
7
|
|
|
8
8
|
install_requires = [
|
|
9
|
-
"stac-fastapi-core==6.
|
|
10
|
-
"sfeos-helpers==6.
|
|
9
|
+
"stac-fastapi-core==6.5.1",
|
|
10
|
+
"sfeos-helpers==6.5.1",
|
|
11
11
|
"opensearch-py~=2.8.0",
|
|
12
12
|
"opensearch-py[async]~=2.8.0",
|
|
13
13
|
"uvicorn~=0.23.0",
|
{stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi/opensearch/app.py
RENAMED
|
@@ -23,14 +23,19 @@ from stac_fastapi.core.extensions.aggregation import (
|
|
|
23
23
|
EsAggregationExtensionGetRequest,
|
|
24
24
|
EsAggregationExtensionPostRequest,
|
|
25
25
|
)
|
|
26
|
+
from stac_fastapi.core.extensions.collections_search import (
|
|
27
|
+
CollectionsSearchEndpointExtension,
|
|
28
|
+
)
|
|
26
29
|
from stac_fastapi.core.extensions.fields import FieldsExtension
|
|
27
30
|
from stac_fastapi.core.rate_limit import setup_rate_limit
|
|
28
31
|
from stac_fastapi.core.route_dependencies import get_route_dependencies
|
|
29
32
|
from stac_fastapi.core.session import Session
|
|
30
33
|
from stac_fastapi.core.utilities import get_bool_env
|
|
31
|
-
from stac_fastapi.extensions.core import (
|
|
34
|
+
from stac_fastapi.extensions.core import (
|
|
32
35
|
AggregationExtension,
|
|
33
36
|
CollectionSearchExtension,
|
|
37
|
+
CollectionSearchFilterExtension,
|
|
38
|
+
CollectionSearchPostExtension,
|
|
34
39
|
FilterExtension,
|
|
35
40
|
FreeTextExtension,
|
|
36
41
|
SortExtension,
|
|
@@ -57,8 +62,14 @@ logger = logging.getLogger(__name__)
|
|
|
57
62
|
|
|
58
63
|
TRANSACTIONS_EXTENSIONS = get_bool_env("ENABLE_TRANSACTIONS_EXTENSIONS", default=True)
|
|
59
64
|
ENABLE_COLLECTIONS_SEARCH = get_bool_env("ENABLE_COLLECTIONS_SEARCH", default=True)
|
|
65
|
+
ENABLE_COLLECTIONS_SEARCH_ROUTE = get_bool_env(
|
|
66
|
+
"ENABLE_COLLECTIONS_SEARCH_ROUTE", default=False
|
|
67
|
+
)
|
|
60
68
|
logger.info("TRANSACTIONS_EXTENSIONS is set to %s", TRANSACTIONS_EXTENSIONS)
|
|
61
69
|
logger.info("ENABLE_COLLECTIONS_SEARCH is set to %s", ENABLE_COLLECTIONS_SEARCH)
|
|
70
|
+
logger.info(
|
|
71
|
+
"ENABLE_COLLECTIONS_SEARCH_ROUTE is set to %s", ENABLE_COLLECTIONS_SEARCH_ROUTE
|
|
72
|
+
)
|
|
62
73
|
|
|
63
74
|
settings = OpensearchSettings()
|
|
64
75
|
session = Session.create_from_settings(settings)
|
|
@@ -116,16 +127,18 @@ if TRANSACTIONS_EXTENSIONS:
|
|
|
116
127
|
|
|
117
128
|
extensions = [aggregation_extension] + search_extensions
|
|
118
129
|
|
|
119
|
-
#
|
|
120
|
-
|
|
130
|
+
# Collection search related variables
|
|
131
|
+
collections_get_request_model = None
|
|
132
|
+
|
|
133
|
+
if ENABLE_COLLECTIONS_SEARCH or ENABLE_COLLECTIONS_SEARCH_ROUTE:
|
|
121
134
|
# Create collection search extensions
|
|
122
135
|
collection_search_extensions = [
|
|
123
|
-
|
|
136
|
+
QueryExtension(conformance_classes=[QueryConformanceClasses.COLLECTIONS]),
|
|
124
137
|
SortExtension(conformance_classes=[SortConformanceClasses.COLLECTIONS]),
|
|
125
138
|
FieldsExtension(conformance_classes=[FieldsConformanceClasses.COLLECTIONS]),
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
139
|
+
CollectionSearchFilterExtension(
|
|
140
|
+
conformance_classes=[FilterConformanceClasses.COLLECTIONS]
|
|
141
|
+
),
|
|
129
142
|
FreeTextExtension(conformance_classes=[FreeTextConformanceClasses.COLLECTIONS]),
|
|
130
143
|
]
|
|
131
144
|
|
|
@@ -135,7 +148,58 @@ if ENABLE_COLLECTIONS_SEARCH:
|
|
|
135
148
|
)
|
|
136
149
|
collections_get_request_model = collection_search_ext.GET
|
|
137
150
|
|
|
151
|
+
# Create a post request model for collection search
|
|
152
|
+
collection_search_post_request_model = create_post_request_model(
|
|
153
|
+
collection_search_extensions
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# Create collection search extensions if enabled
|
|
157
|
+
if ENABLE_COLLECTIONS_SEARCH:
|
|
158
|
+
# Initialize collection search POST extension
|
|
159
|
+
collection_search_post_ext = CollectionSearchPostExtension(
|
|
160
|
+
client=CoreClient(
|
|
161
|
+
database=database_logic,
|
|
162
|
+
session=session,
|
|
163
|
+
post_request_model=collection_search_post_request_model,
|
|
164
|
+
landing_page_id=os.getenv("STAC_FASTAPI_LANDING_PAGE_ID", "stac-fastapi"),
|
|
165
|
+
),
|
|
166
|
+
settings=settings,
|
|
167
|
+
POST=collection_search_post_request_model,
|
|
168
|
+
conformance_classes=[
|
|
169
|
+
"https://api.stacspec.org/v1.0.0-rc.1/collection-search",
|
|
170
|
+
QueryConformanceClasses.COLLECTIONS,
|
|
171
|
+
FilterConformanceClasses.COLLECTIONS,
|
|
172
|
+
FreeTextConformanceClasses.COLLECTIONS,
|
|
173
|
+
SortConformanceClasses.COLLECTIONS,
|
|
174
|
+
FieldsConformanceClasses.COLLECTIONS,
|
|
175
|
+
],
|
|
176
|
+
)
|
|
138
177
|
extensions.append(collection_search_ext)
|
|
178
|
+
extensions.append(collection_search_post_ext)
|
|
179
|
+
|
|
180
|
+
if ENABLE_COLLECTIONS_SEARCH_ROUTE:
|
|
181
|
+
# Initialize collections-search endpoint extension
|
|
182
|
+
collections_search_endpoint_ext = CollectionsSearchEndpointExtension(
|
|
183
|
+
client=CoreClient(
|
|
184
|
+
database=database_logic,
|
|
185
|
+
session=session,
|
|
186
|
+
post_request_model=collection_search_post_request_model,
|
|
187
|
+
landing_page_id=os.getenv("STAC_FASTAPI_LANDING_PAGE_ID", "stac-fastapi"),
|
|
188
|
+
),
|
|
189
|
+
settings=settings,
|
|
190
|
+
GET=collections_get_request_model,
|
|
191
|
+
POST=collection_search_post_request_model,
|
|
192
|
+
conformance_classes=[
|
|
193
|
+
"https://api.stacspec.org/v1.0.0-rc.1/collection-search",
|
|
194
|
+
QueryConformanceClasses.COLLECTIONS,
|
|
195
|
+
FilterConformanceClasses.COLLECTIONS,
|
|
196
|
+
FreeTextConformanceClasses.COLLECTIONS,
|
|
197
|
+
SortConformanceClasses.COLLECTIONS,
|
|
198
|
+
FieldsConformanceClasses.COLLECTIONS,
|
|
199
|
+
],
|
|
200
|
+
)
|
|
201
|
+
extensions.append(collections_search_endpoint_ext)
|
|
202
|
+
|
|
139
203
|
|
|
140
204
|
database_logic.extensions = [type(ext).__name__ for ext in extensions]
|
|
141
205
|
|
|
@@ -169,14 +233,15 @@ app_config = {
|
|
|
169
233
|
post_request_model=post_request_model,
|
|
170
234
|
landing_page_id=os.getenv("STAC_FASTAPI_LANDING_PAGE_ID", "stac-fastapi"),
|
|
171
235
|
),
|
|
236
|
+
"collections_get_request_model": collections_get_request_model,
|
|
172
237
|
"search_get_request_model": create_get_request_model(search_extensions),
|
|
173
238
|
"search_post_request_model": post_request_model,
|
|
174
239
|
"items_get_request_model": items_get_request_model,
|
|
175
240
|
"route_dependencies": get_route_dependencies(),
|
|
176
241
|
}
|
|
177
242
|
|
|
178
|
-
# Add collections_get_request_model if
|
|
179
|
-
if
|
|
243
|
+
# Add collections_get_request_model if it was created
|
|
244
|
+
if collections_get_request_model:
|
|
180
245
|
app_config["collections_get_request_model"] = collections_get_request_model
|
|
181
246
|
|
|
182
247
|
api = StacApi(**app_config)
|
|
@@ -160,8 +160,11 @@ class DatabaseLogic(BaseDatabaseLogic):
|
|
|
160
160
|
request: Request,
|
|
161
161
|
sort: Optional[List[Dict[str, Any]]] = None,
|
|
162
162
|
q: Optional[List[str]] = None,
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
filter: Optional[Dict[str, Any]] = None,
|
|
164
|
+
query: Optional[Dict[str, Dict[str, Any]]] = None,
|
|
165
|
+
datetime: Optional[str] = None,
|
|
166
|
+
) -> Tuple[List[Dict[str, Any]], Optional[str], Optional[int]]:
|
|
167
|
+
"""Retrieve a list of collections from OpenSearch, supporting pagination.
|
|
165
168
|
|
|
166
169
|
Args:
|
|
167
170
|
token (Optional[str]): The pagination token.
|
|
@@ -169,6 +172,9 @@ class DatabaseLogic(BaseDatabaseLogic):
|
|
|
169
172
|
request (Request): The FastAPI request object.
|
|
170
173
|
sort (Optional[List[Dict[str, Any]]]): Optional sort parameter from the request.
|
|
171
174
|
q (Optional[List[str]]): Free text search terms.
|
|
175
|
+
query (Optional[Dict[str, Dict[str, Any]]]): Query extension parameters.
|
|
176
|
+
filter (Optional[Dict[str, Any]]): Structured query in CQL2 format.
|
|
177
|
+
datetime (Optional[str]): Temporal filter.
|
|
172
178
|
|
|
173
179
|
Returns:
|
|
174
180
|
A tuple of (collections, next pagination token if any).
|
|
@@ -206,8 +212,24 @@ class DatabaseLogic(BaseDatabaseLogic):
|
|
|
206
212
|
"size": limit,
|
|
207
213
|
}
|
|
208
214
|
|
|
215
|
+
# Handle search_after token - split by '|' to get all sort values
|
|
216
|
+
search_after = None
|
|
209
217
|
if token:
|
|
210
|
-
|
|
218
|
+
try:
|
|
219
|
+
# The token should be a pipe-separated string of sort values
|
|
220
|
+
# e.g., "2023-01-01T00:00:00Z|collection-1"
|
|
221
|
+
search_after = token.split("|")
|
|
222
|
+
# If the number of sort fields doesn't match token parts, ignore the token
|
|
223
|
+
if len(search_after) != len(formatted_sort):
|
|
224
|
+
search_after = None
|
|
225
|
+
except Exception:
|
|
226
|
+
search_after = None
|
|
227
|
+
|
|
228
|
+
if search_after is not None:
|
|
229
|
+
body["search_after"] = search_after
|
|
230
|
+
|
|
231
|
+
# Build the query part of the body
|
|
232
|
+
query_parts = []
|
|
211
233
|
|
|
212
234
|
# Apply free text query if provided
|
|
213
235
|
if q:
|
|
@@ -235,16 +257,86 @@ class DatabaseLogic(BaseDatabaseLogic):
|
|
|
235
257
|
}
|
|
236
258
|
)
|
|
237
259
|
|
|
238
|
-
# Add the query to the
|
|
239
|
-
|
|
240
|
-
"bool": {"should": should_clauses, "minimum_should_match": 1}
|
|
241
|
-
|
|
260
|
+
# Add the free text query to the query parts
|
|
261
|
+
query_parts.append(
|
|
262
|
+
{"bool": {"should": should_clauses, "minimum_should_match": 1}}
|
|
263
|
+
)
|
|
242
264
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
265
|
+
# Apply structured filter if provided
|
|
266
|
+
if filter:
|
|
267
|
+
# Convert string filter to dict if needed
|
|
268
|
+
if isinstance(filter, str):
|
|
269
|
+
filter = orjson.loads(filter)
|
|
270
|
+
# Convert the filter to an OpenSearch query using the filter module
|
|
271
|
+
es_query = filter_module.to_es(await self.get_queryables_mapping(), filter)
|
|
272
|
+
query_parts.append(es_query)
|
|
273
|
+
|
|
274
|
+
# Apply query extension if provided
|
|
275
|
+
if query:
|
|
276
|
+
try:
|
|
277
|
+
# First create a search object to apply filters
|
|
278
|
+
search = Search(index=COLLECTIONS_INDEX)
|
|
279
|
+
|
|
280
|
+
# Process each field and operator in the query
|
|
281
|
+
for field_name, expr in query.items():
|
|
282
|
+
for op, value in expr.items():
|
|
283
|
+
# For collections, we don't need to prefix with 'properties__'
|
|
284
|
+
field = field_name
|
|
285
|
+
# Apply the filter using apply_stacql_filter
|
|
286
|
+
search = self.apply_stacql_filter(
|
|
287
|
+
search=search, op=op, field=field, value=value
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
# Convert the search object to a query dict and add it to query_parts
|
|
291
|
+
search_dict = search.to_dict()
|
|
292
|
+
if "query" in search_dict:
|
|
293
|
+
query_parts.append(search_dict["query"])
|
|
294
|
+
|
|
295
|
+
except Exception as e:
|
|
296
|
+
logger.error(f"Error converting query to OpenSearch: {e}")
|
|
297
|
+
# If there's an error, add a query that matches nothing
|
|
298
|
+
query_parts.append({"bool": {"must_not": {"match_all": {}}}})
|
|
299
|
+
raise
|
|
300
|
+
|
|
301
|
+
# Combine all query parts with AND logic if there are multiple
|
|
302
|
+
datetime_filter = None
|
|
303
|
+
if datetime:
|
|
304
|
+
datetime_filter = self._apply_collection_datetime_filter(datetime)
|
|
305
|
+
if datetime_filter:
|
|
306
|
+
query_parts.append(datetime_filter)
|
|
307
|
+
|
|
308
|
+
# Combine all query parts with AND logic
|
|
309
|
+
if query_parts:
|
|
310
|
+
body["query"] = (
|
|
311
|
+
query_parts[0]
|
|
312
|
+
if len(query_parts) == 1
|
|
313
|
+
else {"bool": {"must": query_parts}}
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
# Create a copy of the body for count query (without pagination and sorting)
|
|
317
|
+
count_body = body.copy()
|
|
318
|
+
if "search_after" in count_body:
|
|
319
|
+
del count_body["search_after"]
|
|
320
|
+
count_body["size"] = 0
|
|
321
|
+
|
|
322
|
+
# Create async tasks for both search and count
|
|
323
|
+
search_task = asyncio.create_task(
|
|
324
|
+
self.client.search(
|
|
325
|
+
index=COLLECTIONS_INDEX,
|
|
326
|
+
body=body,
|
|
327
|
+
)
|
|
246
328
|
)
|
|
247
329
|
|
|
330
|
+
count_task = asyncio.create_task(
|
|
331
|
+
self.client.count(
|
|
332
|
+
index=COLLECTIONS_INDEX,
|
|
333
|
+
body={"query": body.get("query", {"match_all": {}})},
|
|
334
|
+
)
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
# Wait for search task to complete
|
|
338
|
+
response = await search_task
|
|
339
|
+
|
|
248
340
|
hits = response["hits"]["hits"]
|
|
249
341
|
collections = [
|
|
250
342
|
self.collection_serializer.db_to_stac(
|
|
@@ -255,12 +347,26 @@ class DatabaseLogic(BaseDatabaseLogic):
|
|
|
255
347
|
|
|
256
348
|
next_token = None
|
|
257
349
|
if len(hits) == limit:
|
|
258
|
-
# Ensure we have a valid sort value for next_token
|
|
259
350
|
next_token_values = hits[-1].get("sort")
|
|
260
351
|
if next_token_values:
|
|
261
|
-
|
|
352
|
+
# Join all sort values with '|' to create the token
|
|
353
|
+
next_token = "|".join(str(val) for val in next_token_values)
|
|
262
354
|
|
|
263
|
-
|
|
355
|
+
# Get the total count of collections
|
|
356
|
+
matched = (
|
|
357
|
+
response["hits"]["total"]["value"]
|
|
358
|
+
if response["hits"]["total"]["relation"] == "eq"
|
|
359
|
+
else None
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
# If count task is done, use its result
|
|
363
|
+
if count_task.done():
|
|
364
|
+
try:
|
|
365
|
+
matched = count_task.result().get("count")
|
|
366
|
+
except Exception as e:
|
|
367
|
+
logger.error(f"Count task failed: {e}")
|
|
368
|
+
|
|
369
|
+
return collections, next_token, matched
|
|
264
370
|
|
|
265
371
|
async def get_one_item(self, collection_id: str, item_id: str) -> Dict:
|
|
266
372
|
"""Retrieve a single item from the database.
|
|
@@ -276,7 +382,7 @@ class DatabaseLogic(BaseDatabaseLogic):
|
|
|
276
382
|
NotFoundError: If the specified Item does not exist in the Collection.
|
|
277
383
|
|
|
278
384
|
Notes:
|
|
279
|
-
The Item is retrieved from the
|
|
385
|
+
The Item is retrieved from the Opensearch database using the `client.get` method,
|
|
280
386
|
with the index for the Collection as the target index and the combined `mk_item_id` as the document id.
|
|
281
387
|
"""
|
|
282
388
|
try:
|
|
@@ -348,6 +454,41 @@ class DatabaseLogic(BaseDatabaseLogic):
|
|
|
348
454
|
search=search, free_text_queries=free_text_queries
|
|
349
455
|
)
|
|
350
456
|
|
|
457
|
+
@staticmethod
|
|
458
|
+
def _apply_collection_datetime_filter(
|
|
459
|
+
datetime_str: Optional[str],
|
|
460
|
+
) -> Optional[Dict[str, Any]]:
|
|
461
|
+
"""Create a temporal filter for collections based on their extent."""
|
|
462
|
+
if not datetime_str:
|
|
463
|
+
return None
|
|
464
|
+
|
|
465
|
+
# Parse the datetime string into start and end
|
|
466
|
+
if "/" in datetime_str:
|
|
467
|
+
start, end = datetime_str.split("/")
|
|
468
|
+
# Replace open-ended ranges with concrete dates
|
|
469
|
+
if start == "..":
|
|
470
|
+
# For open-ended start, use a very early date
|
|
471
|
+
start = "1800-01-01T00:00:00Z"
|
|
472
|
+
if end == "..":
|
|
473
|
+
# For open-ended end, use a far future date
|
|
474
|
+
end = "2999-12-31T23:59:59Z"
|
|
475
|
+
else:
|
|
476
|
+
# If it's just a single date, use it for both start and end
|
|
477
|
+
start = end = datetime_str
|
|
478
|
+
|
|
479
|
+
return {
|
|
480
|
+
"bool": {
|
|
481
|
+
"must": [
|
|
482
|
+
# Check if any date in the array is less than or equal to the query end date
|
|
483
|
+
# This will match if the collection's start date is before or equal to the query end date
|
|
484
|
+
{"range": {"extent.temporal.interval": {"lte": end}}},
|
|
485
|
+
# Check if any date in the array is greater than or equal to the query start date
|
|
486
|
+
# This will match if the collection's end date is after or equal to the query start date
|
|
487
|
+
{"range": {"extent.temporal.interval": {"gte": start}}},
|
|
488
|
+
]
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
351
492
|
@staticmethod
|
|
352
493
|
def apply_datetime_filter(
|
|
353
494
|
search: Search, datetime: Optional[str]
|
|
@@ -542,18 +683,31 @@ class DatabaseLogic(BaseDatabaseLogic):
|
|
|
542
683
|
|
|
543
684
|
Args:
|
|
544
685
|
search (Search): The search object to apply the filter to.
|
|
545
|
-
op (str): The comparison operator to use. Can be 'eq' (equal), '
|
|
546
|
-
'lt' (less than), or 'lte' (less than or equal).
|
|
686
|
+
op (str): The comparison operator to use. Can be 'eq' (equal), 'ne'/'neq' (not equal), 'gt' (greater than),
|
|
687
|
+
'gte' (greater than or equal), 'lt' (less than), or 'lte' (less than or equal).
|
|
547
688
|
field (str): The field to perform the comparison on.
|
|
548
689
|
value (float): The value to compare the field against.
|
|
549
690
|
|
|
550
691
|
Returns:
|
|
551
692
|
search (Search): The search object with the specified filter applied.
|
|
552
693
|
"""
|
|
553
|
-
if op
|
|
554
|
-
|
|
694
|
+
if op == "eq":
|
|
695
|
+
search = search.filter("term", **{field: value})
|
|
696
|
+
elif op == "ne" or op == "neq":
|
|
697
|
+
# For not equal, use a bool query with must_not
|
|
698
|
+
search = search.exclude("term", **{field: value})
|
|
699
|
+
elif op in ["gt", "gte", "lt", "lte"]:
|
|
700
|
+
# For range operators
|
|
701
|
+
key_filter = {field: {op: value}}
|
|
555
702
|
search = search.filter(Q("range", **key_filter))
|
|
556
|
-
|
|
703
|
+
elif op == "in":
|
|
704
|
+
# For in operator (value should be a list)
|
|
705
|
+
if isinstance(value, list):
|
|
706
|
+
search = search.filter("terms", **{field: value})
|
|
707
|
+
else:
|
|
708
|
+
search = search.filter("term", **{field: value})
|
|
709
|
+
elif op == "contains":
|
|
710
|
+
# For contains operator (for arrays)
|
|
557
711
|
search = search.filter("term", **{field: value})
|
|
558
712
|
|
|
559
713
|
return search
|
{stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi/opensearch/version.py
RENAMED
|
@@ -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-opensearch
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.5.1
|
|
4
4
|
Summary: Opensearch stac-fastapi backend.
|
|
5
5
|
Home-page: https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch
|
|
6
6
|
License: MIT
|
|
@@ -87,13 +87,13 @@ This project is built on the following technologies: STAC, stac-fastapi, FastAPI
|
|
|
87
87
|
## Table of Contents
|
|
88
88
|
|
|
89
89
|
- [stac-fastapi-elasticsearch-opensearch](#stac-fastapi-elasticsearch-opensearch)
|
|
90
|
-
- [Sponsors
|
|
90
|
+
- [Sponsors & Supporters](#sponsors--supporters)
|
|
91
91
|
- [Project Introduction - What is SFEOS?](#project-introduction---what-is-sfeos)
|
|
92
92
|
- [Common Deployment Patterns](#common-deployment-patterns)
|
|
93
93
|
- [Technologies](#technologies)
|
|
94
94
|
- [Table of Contents](#table-of-contents)
|
|
95
95
|
- [Collection Search Extensions](#collection-search-extensions)
|
|
96
|
-
- [Documentation
|
|
96
|
+
- [Documentation & Resources](#documentation--resources)
|
|
97
97
|
- [Package Structure](#package-structure)
|
|
98
98
|
- [Examples](#examples)
|
|
99
99
|
- [Performance](#performance)
|
|
@@ -136,7 +136,11 @@ This project is built on the following technologies: STAC, stac-fastapi, FastAPI
|
|
|
136
136
|
|
|
137
137
|
## Collection Search Extensions
|
|
138
138
|
|
|
139
|
-
SFEOS
|
|
139
|
+
SFEOS provides enhanced collection search capabilities through two primary routes:
|
|
140
|
+
- **GET/POST `/collections`**: The standard STAC endpoint with extended query parameters
|
|
141
|
+
- **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)
|
|
142
|
+
|
|
143
|
+
These endpoints support advanced collection discovery features including:
|
|
140
144
|
|
|
141
145
|
- **Sorting**: Sort collections by sortable fields using the `sortby` parameter
|
|
142
146
|
- Example: `/collections?sortby=+id` (ascending sort by ID)
|
|
@@ -152,9 +156,26 @@ SFEOS implements extended capabilities for the `/collections` endpoint, allowing
|
|
|
152
156
|
- Searches across multiple text fields including title, description, and keywords
|
|
153
157
|
- Supports partial word matching and relevance-based sorting
|
|
154
158
|
|
|
159
|
+
- **Structured Filtering**: Filter collections using CQL2 expressions
|
|
160
|
+
- JSON format: `/collections?filter={"op":"=","args":[{"property":"id"},"sentinel-2"]}&filter-lang=cql2-json`
|
|
161
|
+
- Text format: `/collections?filter=id='sentinel-2'&filter-lang=cql2-text` (note: string values must be quoted)
|
|
162
|
+
- Advanced text format: `/collections?filter=id LIKE '%sentinel%'&filter-lang=cql2-text` (supports LIKE, BETWEEN, etc.)
|
|
163
|
+
- Supports both CQL2 JSON and CQL2 text formats with various operators
|
|
164
|
+
- Enables precise filtering on any collection property
|
|
165
|
+
|
|
166
|
+
- **Datetime Filtering**: Filter collections by their temporal extent using the `datetime` parameter
|
|
167
|
+
- Example: `/collections?datetime=2020-01-01T00:00:00Z/2020-12-31T23:59:59Z` (finds collections with temporal extents that overlap this range)
|
|
168
|
+
- Example: `/collections?datetime=2020-06-15T12:00:00Z` (finds collections whose temporal extent includes this specific time)
|
|
169
|
+
- Example: `/collections?datetime=2020-01-01T00:00:00Z/..` (finds collections with temporal extents that extend to or beyond January 1, 2020)
|
|
170
|
+
- Example: `/collections?datetime=../2020-12-31T23:59:59Z` (finds collections with temporal extents that begin on or before December 31, 2020)
|
|
171
|
+
- Collections are matched if their temporal extent overlaps with the provided datetime parameter
|
|
172
|
+
- This allows for efficient discovery of collections based on time periods
|
|
173
|
+
|
|
155
174
|
These extensions make it easier to build user interfaces that display and navigate through collections efficiently.
|
|
156
175
|
|
|
157
|
-
> **Configuration**: Collection search extensions can be disabled by setting the `ENABLE_COLLECTIONS_SEARCH` environment variable to `false`. By default, these extensions are enabled.
|
|
176
|
+
> **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.
|
|
177
|
+
>
|
|
178
|
+
> **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**.
|
|
158
179
|
|
|
159
180
|
> **Note**: Sorting is only available on fields that are indexed for sorting in Elasticsearch/OpenSearch. With the default mappings, you can sort on:
|
|
160
181
|
> - `id` (keyword field)
|
|
@@ -165,6 +186,7 @@ These extensions make it easier to build user interfaces that display and naviga
|
|
|
165
186
|
>
|
|
166
187
|
> **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.
|
|
167
188
|
|
|
189
|
+
|
|
168
190
|
## Package Structure
|
|
169
191
|
|
|
170
192
|
This project is organized into several packages, each with a specific purpose:
|
|
@@ -177,7 +199,7 @@ This project is organized into several packages, each with a specific purpose:
|
|
|
177
199
|
- Shared logic and utilities that improve code reuse between backends
|
|
178
200
|
|
|
179
201
|
- **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`.
|
|
180
|
-
|
|
202
|
+
|
|
181
203
|
- **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`.
|
|
182
204
|
|
|
183
205
|
## Examples
|
|
@@ -295,12 +317,13 @@ You can customize additional settings in your `.env` file:
|
|
|
295
317
|
| `ENABLE_DIRECT_RESPONSE` | Enable direct response for maximum performance (disables all FastAPI dependencies, including authentication, custom status codes, and validation) | `false` | Optional |
|
|
296
318
|
| `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 |
|
|
297
319
|
| `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 |
|
|
298
|
-
| `ENABLE_COLLECTIONS_SEARCH` | Enable collection search extensions (sort, fields).
|
|
299
|
-
| `
|
|
320
|
+
| `ENABLE_COLLECTIONS_SEARCH` | Enable collection search extensions (sort, fields, free text search, structured filtering, and datetime filtering) on the core `/collections` endpoint. | `true` | Optional |
|
|
321
|
+
| `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 |
|
|
322
|
+
| `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 |
|
|
300
323
|
| `STAC_ITEM_LIMIT` | Sets the environment variable for result limiting to SFEOS for the number of returned items and STAC collections. | `10` | Optional |
|
|
301
324
|
| `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 |
|
|
302
325
|
| `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 |
|
|
303
|
-
| `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. |
|
|
326
|
+
| `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 |
|
|
304
327
|
|
|
305
328
|
> [!NOTE]
|
|
306
329
|
> 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.
|
|
@@ -446,7 +469,6 @@ The system uses a precise naming convention:
|
|
|
446
469
|
- `ENABLE_COLLECTIONS_SEARCH`: Set to `true` (default) to enable collection search extensions (sort, fields). Set to `false` to disable.
|
|
447
470
|
- `ENABLE_TRANSACTIONS_EXTENSIONS`: Set to `true` (default) to enable transaction extensions. Set to `false` to disable.
|
|
448
471
|
|
|
449
|
-
|
|
450
472
|
## Collection Pagination
|
|
451
473
|
|
|
452
474
|
- **Overview**: The collections route supports pagination through optional query parameters.
|
|
File without changes
|
{stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi/opensearch/__init__.py
RENAMED
|
File without changes
|
{stac_fastapi_opensearch-6.4.0 → stac_fastapi_opensearch-6.5.1}/stac_fastapi/opensearch/config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|