sfeos-helpers 6.5.0__tar.gz → 6.6.0__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.
- sfeos_helpers-6.6.0/.gitignore +143 -0
- sfeos_helpers-6.6.0/PKG-INFO +43 -0
- sfeos_helpers-6.6.0/README.md +22 -0
- sfeos_helpers-6.6.0/pyproject.toml +47 -0
- sfeos_helpers-6.6.0/stac_fastapi/sfeos_helpers/aggregation/README.md +57 -0
- sfeos_helpers-6.6.0/stac_fastapi/sfeos_helpers/database/README.md +61 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/database/__init__.py +6 -1
- sfeos_helpers-6.6.0/stac_fastapi/sfeos_helpers/database/query.py +255 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/database/utils.py +80 -2
- sfeos_helpers-6.6.0/stac_fastapi/sfeos_helpers/filter/README.md +27 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/mappings.py +1 -1
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/version.py +1 -1
- sfeos_helpers-6.5.0/PKG-INFO +0 -713
- sfeos_helpers-6.5.0/README.md +0 -695
- sfeos_helpers-6.5.0/setup.cfg +0 -7
- sfeos_helpers-6.5.0/setup.py +0 -34
- sfeos_helpers-6.5.0/sfeos_helpers.egg-info/PKG-INFO +0 -713
- sfeos_helpers-6.5.0/sfeos_helpers.egg-info/SOURCES.txt +0 -37
- sfeos_helpers-6.5.0/sfeos_helpers.egg-info/dependency_links.txt +0 -1
- sfeos_helpers-6.5.0/sfeos_helpers.egg-info/not-zip-safe +0 -1
- sfeos_helpers-6.5.0/sfeos_helpers.egg-info/requires.txt +0 -1
- sfeos_helpers-6.5.0/sfeos_helpers.egg-info/top_level.txt +0 -1
- sfeos_helpers-6.5.0/stac_fastapi/sfeos_helpers/database/query.py +0 -120
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/aggregation/__init__.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/aggregation/client.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/aggregation/format.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/database/datetime.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/database/document.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/database/index.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/database/mapping.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/filter/__init__.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/filter/client.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/filter/cql2.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/filter/transform.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/models/patch.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/search_engine/__init__.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/search_engine/base.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/search_engine/factory.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/search_engine/index_operations.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/search_engine/inserters.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/search_engine/managers.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/search_engine/selection/__init__.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/search_engine/selection/base.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/search_engine/selection/cache_manager.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/search_engine/selection/factory.py +0 -0
- {sfeos_helpers-6.5.0 → sfeos_helpers-6.6.0}/stac_fastapi/sfeos_helpers/search_engine/selection/selectors.py +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
elasticsearch/snapshots/
|
|
2
|
+
|
|
3
|
+
# Byte-compiled / optimized / DLL files
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[cod]
|
|
6
|
+
*$py.class
|
|
7
|
+
|
|
8
|
+
# C extensions
|
|
9
|
+
*.so
|
|
10
|
+
|
|
11
|
+
# Distribution / packaging
|
|
12
|
+
.Python
|
|
13
|
+
build/
|
|
14
|
+
develop-eggs/
|
|
15
|
+
dist/
|
|
16
|
+
downloads/
|
|
17
|
+
eggs/
|
|
18
|
+
.eggs/
|
|
19
|
+
lib/
|
|
20
|
+
lib64/
|
|
21
|
+
parts/
|
|
22
|
+
sdist/
|
|
23
|
+
var/
|
|
24
|
+
wheels/
|
|
25
|
+
pip-wheel-metadata/
|
|
26
|
+
share/python-wheels/
|
|
27
|
+
*.egg-info/
|
|
28
|
+
.installed.cfg
|
|
29
|
+
*.egg
|
|
30
|
+
MANIFEST
|
|
31
|
+
|
|
32
|
+
# PyInstaller
|
|
33
|
+
# Usually these files are written by a python script from a template
|
|
34
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
35
|
+
*.manifest
|
|
36
|
+
*.spec
|
|
37
|
+
|
|
38
|
+
# Installer logs
|
|
39
|
+
pip-log.txt
|
|
40
|
+
pip-delete-this-directory.txt
|
|
41
|
+
|
|
42
|
+
# Unit test / coverage reports
|
|
43
|
+
htmlcov/
|
|
44
|
+
.tox/
|
|
45
|
+
.nox/
|
|
46
|
+
.coverage
|
|
47
|
+
.coverage.*
|
|
48
|
+
.cache
|
|
49
|
+
nosetests.xml
|
|
50
|
+
coverage.xml
|
|
51
|
+
*.cover
|
|
52
|
+
*.py,cover
|
|
53
|
+
.hypothesis/
|
|
54
|
+
.pytest_cache/
|
|
55
|
+
|
|
56
|
+
# Translations
|
|
57
|
+
*.mo
|
|
58
|
+
*.pot
|
|
59
|
+
|
|
60
|
+
# Django stuff:
|
|
61
|
+
*.log
|
|
62
|
+
local_settings.py
|
|
63
|
+
db.sqlite3
|
|
64
|
+
db.sqlite3-journal
|
|
65
|
+
|
|
66
|
+
# Flask stuff:
|
|
67
|
+
instance/
|
|
68
|
+
.webassets-cache
|
|
69
|
+
|
|
70
|
+
# Scrapy stuff:
|
|
71
|
+
.scrapy
|
|
72
|
+
|
|
73
|
+
# Sphinx documentation
|
|
74
|
+
docs/_build/
|
|
75
|
+
|
|
76
|
+
# PyBuilder
|
|
77
|
+
target/
|
|
78
|
+
|
|
79
|
+
# Jupyter Notebook
|
|
80
|
+
.ipynb_checkpoints
|
|
81
|
+
|
|
82
|
+
# IPython
|
|
83
|
+
profile_default/
|
|
84
|
+
ipython_config.py
|
|
85
|
+
|
|
86
|
+
# pyenv
|
|
87
|
+
.python-version
|
|
88
|
+
|
|
89
|
+
# pipenv
|
|
90
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
91
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
92
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
93
|
+
# install all needed dependencies.
|
|
94
|
+
#Pipfile.lock
|
|
95
|
+
|
|
96
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
97
|
+
__pypackages__/
|
|
98
|
+
|
|
99
|
+
# Celery stuff
|
|
100
|
+
celerybeat-schedule
|
|
101
|
+
celerybeat.pid
|
|
102
|
+
|
|
103
|
+
# SageMath parsed files
|
|
104
|
+
*.sage.py
|
|
105
|
+
|
|
106
|
+
# Environments
|
|
107
|
+
.env
|
|
108
|
+
.venv
|
|
109
|
+
env/
|
|
110
|
+
venv/
|
|
111
|
+
ENV/
|
|
112
|
+
env.bak/
|
|
113
|
+
venv.bak/
|
|
114
|
+
|
|
115
|
+
# Spyder project settings
|
|
116
|
+
.spyderproject
|
|
117
|
+
.spyproject
|
|
118
|
+
|
|
119
|
+
# Rope project settings
|
|
120
|
+
.ropeproject
|
|
121
|
+
|
|
122
|
+
# mkdocs documentation
|
|
123
|
+
/site
|
|
124
|
+
|
|
125
|
+
# mypy
|
|
126
|
+
.mypy_cache/
|
|
127
|
+
.dmypy.json
|
|
128
|
+
dmypy.json
|
|
129
|
+
|
|
130
|
+
# Pyre type checker
|
|
131
|
+
.pyre/
|
|
132
|
+
|
|
133
|
+
/esdata
|
|
134
|
+
|
|
135
|
+
# Virtualenv
|
|
136
|
+
venv
|
|
137
|
+
|
|
138
|
+
# VSCode folder
|
|
139
|
+
.vscode
|
|
140
|
+
|
|
141
|
+
/docs/src/api/*
|
|
142
|
+
|
|
143
|
+
.DS_Store
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sfeos_helpers
|
|
3
|
+
Version: 6.6.0
|
|
4
|
+
Summary: Helper library for the Elasticsearch and Opensearch stac-fastapi backends.
|
|
5
|
+
Project-URL: Homepage, https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: Elasticsearch,FastAPI,Opensearch,STAC,STAC-API,stac-fastapi
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: Intended Audience :: Information Technology
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Requires-Dist: stac-fastapi-core==6.6.0
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# sfeos-helpers
|
|
23
|
+
|
|
24
|
+
Helper utilities for the stac-fastapi project. For full documentation, please see the [main README](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/blob/main/README.md).
|
|
25
|
+
|
|
26
|
+
## Package Information
|
|
27
|
+
|
|
28
|
+
- **Package name**: sfeos-helpers
|
|
29
|
+
- **Description**: Helper utilities for the stac-fastapi project.
|
|
30
|
+
- **Documentation**: [https://stac-utils.github.io/stac-fastapi-elasticsearch-opensearch/](https://stac-utils.github.io/stac-fastapi-elasticsearch-opensearch/)
|
|
31
|
+
- **Source**: [GitHub Repository](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/)
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
This package is a dependency of stac-fastapi-elasticsearch and stac-fastapi-opensearch and is typically installed automatically.
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install stac-fastapi-elasticsearch # or stac-fastapi-opensearch
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
For detailed usage and examples, please refer to the [main documentation](https://stac-utils.github.io/stac-fastapi-elasticsearch-opensearch/).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# sfeos-helpers
|
|
2
|
+
|
|
3
|
+
Helper utilities for the stac-fastapi project. For full documentation, please see the [main README](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/blob/main/README.md).
|
|
4
|
+
|
|
5
|
+
## Package Information
|
|
6
|
+
|
|
7
|
+
- **Package name**: sfeos-helpers
|
|
8
|
+
- **Description**: Helper utilities for the stac-fastapi project.
|
|
9
|
+
- **Documentation**: [https://stac-utils.github.io/stac-fastapi-elasticsearch-opensearch/](https://stac-utils.github.io/stac-fastapi-elasticsearch-opensearch/)
|
|
10
|
+
- **Source**: [GitHub Repository](https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch/)
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
This package is a dependency of stac-fastapi-elasticsearch and stac-fastapi-opensearch and is typically installed automatically.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install stac-fastapi-elasticsearch # or stac-fastapi-opensearch
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
For detailed usage and examples, please refer to the [main documentation](https://stac-utils.github.io/stac-fastapi-elasticsearch-opensearch/).
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sfeos_helpers"
|
|
7
|
+
description = "Helper library for the Elasticsearch and Opensearch stac-fastapi backends."
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
requires-python = ">=3.9"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
authors = []
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"Intended Audience :: Information Technology",
|
|
15
|
+
"Intended Audience :: Science/Research",
|
|
16
|
+
"Programming Language :: Python :: 3.9",
|
|
17
|
+
"Programming Language :: Python :: 3.10",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
21
|
+
"Programming Language :: Python :: 3.14",
|
|
22
|
+
"License :: OSI Approved :: MIT License",
|
|
23
|
+
]
|
|
24
|
+
keywords = [
|
|
25
|
+
"STAC",
|
|
26
|
+
"STAC-API",
|
|
27
|
+
"FastAPI",
|
|
28
|
+
"stac-fastapi",
|
|
29
|
+
"Elasticsearch",
|
|
30
|
+
"Opensearch",
|
|
31
|
+
]
|
|
32
|
+
dynamic = ["version"]
|
|
33
|
+
dependencies = [
|
|
34
|
+
"stac-fastapi.core==6.6.0",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Homepage = "https://github.com/stac-utils/stac-fastapi-elasticsearch-opensearch"
|
|
39
|
+
|
|
40
|
+
[tool.hatch.version]
|
|
41
|
+
path = "stac_fastapi/sfeos_helpers/version.py"
|
|
42
|
+
|
|
43
|
+
[tool.hatch.build.targets.sdist]
|
|
44
|
+
exclude = ["alembic", "tests", "scripts"]
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.wheel]
|
|
47
|
+
only-include = ["stac_fastapi"]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# STAC FastAPI Aggregation Package
|
|
2
|
+
|
|
3
|
+
This package contains shared aggregation functionality used by both the Elasticsearch and OpenSearch implementations of STAC FastAPI. It helps reduce code duplication and ensures consistent behavior between the two implementations.
|
|
4
|
+
|
|
5
|
+
## Package Structure
|
|
6
|
+
|
|
7
|
+
The aggregation package is organized into three main modules:
|
|
8
|
+
|
|
9
|
+
- **client.py**: Contains the base aggregation client implementation
|
|
10
|
+
- `EsAsyncBaseAggregationClient`: The main class that implements the STAC aggregation extension for Elasticsearch/OpenSearch
|
|
11
|
+
- Methods for handling aggregation requests, validating parameters, and formatting responses
|
|
12
|
+
|
|
13
|
+
- **format.py**: Contains functions for formatting aggregation responses
|
|
14
|
+
- `frequency_agg`: Formats frequency distribution aggregation responses
|
|
15
|
+
- `metric_agg`: Formats metric aggregation responses
|
|
16
|
+
|
|
17
|
+
- **__init__.py**: Package initialization and exports
|
|
18
|
+
- Exports the main classes and functions for use by other modules
|
|
19
|
+
|
|
20
|
+
## Features
|
|
21
|
+
|
|
22
|
+
The aggregation package provides the following features:
|
|
23
|
+
|
|
24
|
+
- Support for various aggregation types:
|
|
25
|
+
- Datetime frequency
|
|
26
|
+
- Collection frequency
|
|
27
|
+
- Property frequency
|
|
28
|
+
- Geospatial grid aggregations (geohash, geohex, geotile)
|
|
29
|
+
- Metric aggregations (min, max, etc.)
|
|
30
|
+
|
|
31
|
+
- Parameter validation:
|
|
32
|
+
- Precision validation for geospatial aggregations
|
|
33
|
+
- Interval validation for datetime aggregations
|
|
34
|
+
|
|
35
|
+
- Response formatting:
|
|
36
|
+
- Consistent response structure
|
|
37
|
+
- Proper typing and documentation
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
The aggregation package is used by the Elasticsearch and OpenSearch implementations to provide aggregation functionality for STAC API. The main entry point is the `EsAsyncBaseAggregationClient` class, which is instantiated in the respective app.py files.
|
|
42
|
+
|
|
43
|
+
Example:
|
|
44
|
+
```python
|
|
45
|
+
from stac_fastapi.sfeos_helpers.aggregation import EsAsyncBaseAggregationClient
|
|
46
|
+
|
|
47
|
+
# Create an instance of the aggregation client
|
|
48
|
+
aggregation_client = EsAsyncBaseAggregationClient(database)
|
|
49
|
+
|
|
50
|
+
# Register the aggregation extension with the API
|
|
51
|
+
api = StacApi(
|
|
52
|
+
...,
|
|
53
|
+
extensions=[
|
|
54
|
+
...,
|
|
55
|
+
AggregationExtension(client=aggregation_client),
|
|
56
|
+
],
|
|
57
|
+
)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# STAC FastAPI Database Package
|
|
2
|
+
|
|
3
|
+
This package contains shared database operations used by both the Elasticsearch and OpenSearch
|
|
4
|
+
implementations of STAC FastAPI. It helps reduce code duplication and ensures consistent behavior
|
|
5
|
+
between the two implementations.
|
|
6
|
+
|
|
7
|
+
## Package Structure
|
|
8
|
+
|
|
9
|
+
The database package is organized into five main modules:
|
|
10
|
+
|
|
11
|
+
- **index.py**: Contains functions for managing indices
|
|
12
|
+
- [create_index_templates_shared](cci:1://file:///home/computer/Code/stac-fastapi-elasticsearch-opensearch/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/database_logic_helpers.py:15:0-48:33): Creates index templates for Collections and Items
|
|
13
|
+
- [delete_item_index_shared](cci:1://file:///home/computer/Code/stac-fastapi-elasticsearch-opensearch/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/database_logic_helpers.py:128:0-153:30): Deletes an item index for a collection
|
|
14
|
+
- [index_by_collection_id](cci:1://file:///home/computer/Code/stac-fastapi-elasticsearch-opensearch/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/utilities.py:86:0-100:5): Translates a collection ID into an index name
|
|
15
|
+
- [index_alias_by_collection_id](cci:1://file:///home/computer/Code/stac-fastapi-elasticsearch-opensearch/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/utilities.py:103:0-115:5): Translates a collection ID into an index alias
|
|
16
|
+
- [indices](cci:1://file:///home/computer/Code/stac-fastapi-elasticsearch-opensearch/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/utilities.py:118:0-132:5): Gets a comma-separated string of index names
|
|
17
|
+
|
|
18
|
+
- **query.py**: Contains functions for building and manipulating queries
|
|
19
|
+
- [apply_free_text_filter_shared](cci:1://file:///home/computer/Code/stac-fastapi-elasticsearch-opensearch/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/database_logic_helpers.py:51:0-74:16): Applies a free text filter to a search
|
|
20
|
+
- [apply_intersects_filter_shared](cci:1://file:///home/computer/Code/stac-fastapi-elasticsearch-opensearch/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/database_logic_helpers.py:77:0-104:5): Creates a geo_shape filter for intersecting geometry
|
|
21
|
+
- [populate_sort_shared](cci:1://file:///home/computer/Code/stac-fastapi-elasticsearch-opensearch/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/database_logic_helpers.py:107:0-125:16): Creates a sort configuration for queries
|
|
22
|
+
|
|
23
|
+
- **mapping.py**: Contains functions for working with mappings
|
|
24
|
+
- [get_queryables_mapping_shared](cci:1://file:///home/computer/Code/stac-fastapi-elasticsearch-opensearch/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/database_logic_helpers.py:156:0-185:27): Retrieves mapping of Queryables for search
|
|
25
|
+
|
|
26
|
+
- **document.py**: Contains functions for working with documents
|
|
27
|
+
- [mk_item_id](cci:1://file:///home/computer/Code/stac-fastapi-elasticsearch-opensearch/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/utilities.py:140:0-150:5): Creates a document ID for an Item
|
|
28
|
+
- [mk_actions](cci:1://file:///home/computer/Code/stac-fastapi-elasticsearch-opensearch/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/utilities.py:153:0-175:5): Creates bulk actions for indexing items
|
|
29
|
+
|
|
30
|
+
- **utils.py**: Contains utility functions for database operations
|
|
31
|
+
- [validate_refresh](cci:1://file:///home/computer/Code/stac-fastapi-elasticsearch-opensearch/stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/utilities.py:41:0-78:5): Validates the refresh parameter value
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
Import the necessary components from the database package:
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from stac_fastapi.sfeos_helpers.database import (
|
|
39
|
+
# Index operations
|
|
40
|
+
create_index_templates_shared,
|
|
41
|
+
delete_item_index_shared,
|
|
42
|
+
index_alias_by_collection_id,
|
|
43
|
+
index_by_collection_id,
|
|
44
|
+
indices,
|
|
45
|
+
|
|
46
|
+
# Query operations
|
|
47
|
+
apply_free_text_filter_shared,
|
|
48
|
+
apply_intersects_filter_shared,
|
|
49
|
+
populate_sort_shared,
|
|
50
|
+
|
|
51
|
+
# Mapping operations
|
|
52
|
+
get_queryables_mapping_shared,
|
|
53
|
+
|
|
54
|
+
# Document operations
|
|
55
|
+
mk_item_id,
|
|
56
|
+
mk_actions,
|
|
57
|
+
|
|
58
|
+
# Utility functions
|
|
59
|
+
validate_refresh,
|
|
60
|
+
)
|
|
61
|
+
```
|
|
@@ -42,11 +42,13 @@ from .index import (
|
|
|
42
42
|
)
|
|
43
43
|
from .mapping import get_queryables_mapping_shared
|
|
44
44
|
from .query import (
|
|
45
|
+
apply_collections_bbox_filter_shared,
|
|
46
|
+
apply_collections_datetime_filter_shared,
|
|
45
47
|
apply_free_text_filter_shared,
|
|
46
48
|
apply_intersects_filter_shared,
|
|
47
49
|
populate_sort_shared,
|
|
48
50
|
)
|
|
49
|
-
from .utils import get_bool_env, validate_refresh
|
|
51
|
+
from .utils import add_bbox_shape_to_collection, get_bool_env, validate_refresh
|
|
50
52
|
|
|
51
53
|
__all__ = [
|
|
52
54
|
# Index operations
|
|
@@ -59,6 +61,8 @@ __all__ = [
|
|
|
59
61
|
# Query operations
|
|
60
62
|
"apply_free_text_filter_shared",
|
|
61
63
|
"apply_intersects_filter_shared",
|
|
64
|
+
"apply_collections_bbox_filter_shared",
|
|
65
|
+
"apply_collections_datetime_filter_shared",
|
|
62
66
|
"populate_sort_shared",
|
|
63
67
|
# Mapping operations
|
|
64
68
|
"get_queryables_mapping_shared",
|
|
@@ -68,6 +72,7 @@ __all__ = [
|
|
|
68
72
|
# Utility functions
|
|
69
73
|
"validate_refresh",
|
|
70
74
|
"get_bool_env",
|
|
75
|
+
"add_bbox_shape_to_collection",
|
|
71
76
|
# Datetime utilities
|
|
72
77
|
"return_date",
|
|
73
78
|
"extract_date",
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"""Query building functions for Elasticsearch/OpenSearch.
|
|
2
|
+
|
|
3
|
+
This module provides functions for building and manipulating Elasticsearch/OpenSearch queries.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
from typing import Any, Dict, List, Optional, Union
|
|
8
|
+
|
|
9
|
+
from stac_fastapi.core.utilities import bbox2polygon
|
|
10
|
+
from stac_fastapi.sfeos_helpers.mappings import Geometry
|
|
11
|
+
|
|
12
|
+
ES_MAX_URL_LENGTH = 4096
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def apply_free_text_filter_shared(
|
|
16
|
+
search: Any, free_text_queries: Optional[List[str]]
|
|
17
|
+
) -> Any:
|
|
18
|
+
"""Create a free text query for Elasticsearch/OpenSearch.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
search (Any): The search object to apply the query to.
|
|
22
|
+
free_text_queries (Optional[List[str]]): A list of text strings to search for in the properties.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Any: The search object with the free text query applied, or the original search
|
|
26
|
+
object if no free_text_queries were provided.
|
|
27
|
+
|
|
28
|
+
Notes:
|
|
29
|
+
This function creates a query_string query that searches for the specified text strings
|
|
30
|
+
in all properties of the documents. The query strings are joined with OR operators.
|
|
31
|
+
"""
|
|
32
|
+
if free_text_queries is not None:
|
|
33
|
+
free_text_query_string = '" OR properties.\\*:"'.join(free_text_queries)
|
|
34
|
+
search = search.query(
|
|
35
|
+
"query_string", query=f'properties.\\*:"{free_text_query_string}"'
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
return search
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def apply_intersects_filter_shared(
|
|
42
|
+
intersects: Geometry,
|
|
43
|
+
) -> Dict[str, Dict]:
|
|
44
|
+
"""Create a geo_shape filter for intersecting geometry.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
intersects (Geometry): The intersecting geometry, represented as a GeoJSON-like object.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Dict[str, Dict]: A dictionary containing the geo_shape filter configuration
|
|
51
|
+
that can be used with Elasticsearch/OpenSearch Q objects.
|
|
52
|
+
|
|
53
|
+
Notes:
|
|
54
|
+
This function creates a geo_shape filter configuration to find documents that intersect
|
|
55
|
+
with the specified geometry. The returned dictionary should be wrapped in a Q object
|
|
56
|
+
when applied to a search.
|
|
57
|
+
"""
|
|
58
|
+
return {
|
|
59
|
+
"geo_shape": {
|
|
60
|
+
"geometry": {
|
|
61
|
+
"shape": {
|
|
62
|
+
"type": intersects.type.lower(),
|
|
63
|
+
"coordinates": intersects.coordinates,
|
|
64
|
+
},
|
|
65
|
+
"relation": "intersects",
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def apply_collections_datetime_filter_shared(
|
|
72
|
+
datetime_str: Optional[str],
|
|
73
|
+
) -> Optional[Dict[str, Any]]:
|
|
74
|
+
"""Create a temporal filter for collections based on their extent.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
datetime_str: The datetime parameter. Can be:
|
|
78
|
+
- A single datetime string (e.g., "2020-01-01T00:00:00Z")
|
|
79
|
+
- A datetime range with "/" separator (e.g., "2020-01-01T00:00:00Z/2021-01-01T00:00:00Z")
|
|
80
|
+
- Open-ended ranges using ".." (e.g., "../2021-01-01T00:00:00Z" or "2020-01-01T00:00:00Z/..")
|
|
81
|
+
- None if no datetime filter is provided
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Optional[Dict[str, Any]]: A dictionary containing the temporal filter configuration
|
|
85
|
+
that can be used with Elasticsearch/OpenSearch queries, or None if datetime_str is None.
|
|
86
|
+
Example return value:
|
|
87
|
+
{
|
|
88
|
+
"bool": {
|
|
89
|
+
"must": [
|
|
90
|
+
{"range": {"extent.temporal.interval": {"lte": "2021-01-01T00:00:00Z"}}},
|
|
91
|
+
{"range": {"extent.temporal.interval": {"gte": "2020-01-01T00:00:00Z"}}}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
Notes:
|
|
97
|
+
- This function is specifically for filtering collections by their temporal extent
|
|
98
|
+
- It queries the extent.temporal.interval field
|
|
99
|
+
- Open-ended ranges (..) are replaced with concrete dates (1800-01-01 for start, 2999-12-31 for end)
|
|
100
|
+
"""
|
|
101
|
+
if not datetime_str:
|
|
102
|
+
return None
|
|
103
|
+
|
|
104
|
+
# Parse the datetime string into start and end
|
|
105
|
+
if "/" in datetime_str:
|
|
106
|
+
start, end = datetime_str.split("/")
|
|
107
|
+
# Replace open-ended ranges with concrete dates
|
|
108
|
+
if start == "..":
|
|
109
|
+
# For open-ended start, use a very early date
|
|
110
|
+
start = "1800-01-01T00:00:00Z"
|
|
111
|
+
if end == "..":
|
|
112
|
+
# For open-ended end, use a far future date
|
|
113
|
+
end = "2999-12-31T23:59:59Z"
|
|
114
|
+
else:
|
|
115
|
+
# If it's just a single date, use it for both start and end
|
|
116
|
+
start = end = datetime_str
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
"bool": {
|
|
120
|
+
"must": [
|
|
121
|
+
# Check if any date in the array is less than or equal to the query end date
|
|
122
|
+
# This will match if the collection's start date is before or equal to the query end date
|
|
123
|
+
{"range": {"extent.temporal.interval": {"lte": end}}},
|
|
124
|
+
# Check if any date in the array is greater than or equal to the query start date
|
|
125
|
+
# This will match if the collection's end date is after or equal to the query start date
|
|
126
|
+
{"range": {"extent.temporal.interval": {"gte": start}}},
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def apply_collections_bbox_filter_shared(
|
|
133
|
+
bbox: Union[str, List[float], None]
|
|
134
|
+
) -> Optional[Dict[str, Dict]]:
|
|
135
|
+
"""Create a geo_shape filter for collections bbox search.
|
|
136
|
+
|
|
137
|
+
This function handles bbox parsing from both GET requests (string format) and POST requests
|
|
138
|
+
(list format), and constructs a geo_shape query for filtering collections by their bbox_shape field.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
bbox: The bounding box parameter. Can be:
|
|
142
|
+
- A string of comma-separated coordinates (from GET requests)
|
|
143
|
+
- A list of floats [minx, miny, maxx, maxy] for 2D bbox
|
|
144
|
+
- None if no bbox filter is provided
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
Optional[Dict[str, Dict]]: A dictionary containing the geo_shape filter configuration
|
|
148
|
+
that can be used with Elasticsearch/OpenSearch queries, or None if bbox is invalid.
|
|
149
|
+
Example return value:
|
|
150
|
+
{
|
|
151
|
+
"geo_shape": {
|
|
152
|
+
"bbox_shape": {
|
|
153
|
+
"shape": {
|
|
154
|
+
"type": "Polygon",
|
|
155
|
+
"coordinates": [[[minx, miny], [maxx, miny], [maxx, maxy], [minx, maxy], [minx, miny]]]
|
|
156
|
+
},
|
|
157
|
+
"relation": "intersects"
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
Notes:
|
|
163
|
+
- This function is specifically for filtering collections by their spatial extent
|
|
164
|
+
- It queries the bbox_shape field (not the geometry field used for items)
|
|
165
|
+
- The bbox is expected to be 2D (4 values) after any 3D to 2D conversion in the API layer
|
|
166
|
+
"""
|
|
167
|
+
logger = logging.getLogger(__name__)
|
|
168
|
+
|
|
169
|
+
if not bbox:
|
|
170
|
+
return None
|
|
171
|
+
|
|
172
|
+
# Parse bbox if it's a string (from GET requests)
|
|
173
|
+
if isinstance(bbox, str):
|
|
174
|
+
try:
|
|
175
|
+
bbox = [float(x.strip()) for x in bbox.split(",")]
|
|
176
|
+
except (ValueError, AttributeError) as e:
|
|
177
|
+
logger.error(f"Invalid bbox format: {bbox}, error: {e}")
|
|
178
|
+
return None
|
|
179
|
+
|
|
180
|
+
if not bbox or len(bbox) != 4:
|
|
181
|
+
if bbox:
|
|
182
|
+
logger.warning(
|
|
183
|
+
f"bbox has incorrect number of coordinates (length={len(bbox)}), expected 4 (2D bbox)"
|
|
184
|
+
)
|
|
185
|
+
return None
|
|
186
|
+
|
|
187
|
+
# Convert bbox to a polygon for geo_shape query
|
|
188
|
+
bbox_polygon = {
|
|
189
|
+
"type": "Polygon",
|
|
190
|
+
"coordinates": bbox2polygon(bbox[0], bbox[1], bbox[2], bbox[3]),
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
# Return geo_shape query for bbox_shape field
|
|
194
|
+
return {
|
|
195
|
+
"geo_shape": {
|
|
196
|
+
"bbox_shape": {
|
|
197
|
+
"shape": bbox_polygon,
|
|
198
|
+
"relation": "intersects",
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def populate_sort_shared(sortby: List) -> Optional[Dict[str, Dict[str, str]]]:
|
|
205
|
+
"""Create a sort configuration for Elasticsearch/OpenSearch queries.
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
sortby (List): A list of sort specifications, each containing a field and direction.
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
Optional[Dict[str, Dict[str, str]]]: A dictionary mapping field names to sort direction
|
|
212
|
+
configurations, or None if no sort was specified.
|
|
213
|
+
|
|
214
|
+
Notes:
|
|
215
|
+
This function transforms a list of sort specifications into the format required by
|
|
216
|
+
Elasticsearch/OpenSearch for sorting query results. The returned dictionary can be
|
|
217
|
+
directly used in search requests.
|
|
218
|
+
Always includes 'id' as secondary sort to ensure unique pagination tokens.
|
|
219
|
+
"""
|
|
220
|
+
if sortby:
|
|
221
|
+
sort_config = {s.field: {"order": s.direction} for s in sortby}
|
|
222
|
+
sort_config.setdefault("id", {"order": "asc"})
|
|
223
|
+
return sort_config
|
|
224
|
+
else:
|
|
225
|
+
return {"id": {"order": "asc"}}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def add_collections_to_body(
|
|
229
|
+
collection_ids: List[str], query: Optional[Dict[str, Any]]
|
|
230
|
+
) -> Dict[str, Any]:
|
|
231
|
+
"""Add a list of collection ids to the body of a query.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
collection_ids (List[str]): A list of collections ids.
|
|
235
|
+
query (Optional[Dict[str, Any]]): The query to add collections to. If none, create a query that filters
|
|
236
|
+
the collection ids.
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Dict[str, Any]: A query that contains a filter on the given collection ids.
|
|
240
|
+
|
|
241
|
+
Notes:
|
|
242
|
+
This function is needed in the execute_search function when the size of the URL path will exceed the maximum of ES.
|
|
243
|
+
"""
|
|
244
|
+
index_filter = {"terms": {"collection": collection_ids}}
|
|
245
|
+
if query is None:
|
|
246
|
+
query = {"query": {}}
|
|
247
|
+
if "bool" not in query:
|
|
248
|
+
query["bool"] = {}
|
|
249
|
+
if "filter" not in query["bool"]:
|
|
250
|
+
query["bool"]["filter"] = []
|
|
251
|
+
|
|
252
|
+
filters = query["bool"]["filter"]
|
|
253
|
+
if index_filter not in filters:
|
|
254
|
+
filters.append(index_filter)
|
|
255
|
+
return query
|