Skip to content

Commit 36504af

Browse files
committed
move utility functions
1 parent a432274 commit 36504af

File tree

11 files changed

+220
-200
lines changed

11 files changed

+220
-200
lines changed

stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/config.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
from elasticsearch import Elasticsearch # type: ignore[attr-defined]
1212
from stac_fastapi.core.base_settings import ApiBaseSettings
13-
from stac_fastapi.sfeos_helpers.utilities import get_bool_env, validate_refresh
13+
from stac_fastapi.core.utilities import get_bool_env
14+
from stac_fastapi.sfeos_helpers.database import validate_refresh
1415
from stac_fastapi.types.config import ApiSettings
1516

1617

stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/database_logic.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@
2727
create_index_templates_shared,
2828
delete_item_index_shared,
2929
get_queryables_mapping_shared,
30+
index_alias_by_collection_id,
31+
index_by_collection_id,
32+
indices,
33+
mk_actions,
34+
mk_item_id,
3035
populate_sort_shared,
36+
validate_refresh,
3137
)
3238
from stac_fastapi.sfeos_helpers.mappings import (
3339
AGGREGATION_MAPPING,
@@ -37,14 +43,6 @@
3743
ITEMS_INDEX_PREFIX,
3844
Geometry,
3945
)
40-
from stac_fastapi.sfeos_helpers.utilities import (
41-
index_alias_by_collection_id,
42-
index_by_collection_id,
43-
indices,
44-
mk_actions,
45-
mk_item_id,
46-
validate_refresh,
47-
)
4846
from stac_fastapi.types.errors import ConflictError, NotFoundError
4947
from stac_fastapi.types.stac import Collection, Item
5048

stac_fastapi/opensearch/stac_fastapi/opensearch/config.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
from opensearchpy import AsyncOpenSearch, OpenSearch
99

1010
from stac_fastapi.core.base_settings import ApiBaseSettings
11-
from stac_fastapi.sfeos_helpers.utilities import get_bool_env, validate_refresh
11+
from stac_fastapi.core.utilities import get_bool_env
12+
from stac_fastapi.sfeos_helpers.database import validate_refresh
1213
from stac_fastapi.types.config import ApiSettings
1314

1415

stac_fastapi/opensearch/stac_fastapi/opensearch/database_logic.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@
2727
create_index_templates_shared,
2828
delete_item_index_shared,
2929
get_queryables_mapping_shared,
30+
index_alias_by_collection_id,
31+
index_by_collection_id,
32+
indices,
33+
mk_actions,
34+
mk_item_id,
3035
populate_sort_shared,
36+
validate_refresh,
3137
)
3238
from stac_fastapi.sfeos_helpers.mappings import (
3339
AGGREGATION_MAPPING,
@@ -40,14 +46,6 @@
4046
ITEMS_INDEX_PREFIX,
4147
Geometry,
4248
)
43-
from stac_fastapi.sfeos_helpers.utilities import (
44-
index_alias_by_collection_id,
45-
index_by_collection_id,
46-
indices,
47-
mk_actions,
48-
mk_item_id,
49-
validate_refresh,
50-
)
5149
from stac_fastapi.types.errors import ConflictError, NotFoundError
5250
from stac_fastapi.types.stac import Collection, Item
5351

stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/database/README.md

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@ between the two implementations.
66

77
## Package Structure
88

9-
The database package is organized into three main modules:
9+
The database package is organized into five main modules:
1010

1111
- **index.py**: Contains functions for managing indices
1212
- [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
1313
- [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
1417

1518
- **query.py**: Contains functions for building and manipulating queries
1619
- [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,16 +23,39 @@ The database package is organized into three main modules:
2023
- **mapping.py**: Contains functions for working with mappings
2124
- [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
2225

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+
2333
## Usage
2434

2535
Import the necessary components from the database package:
2636

2737
```python
2838
from stac_fastapi.sfeos_helpers.database import (
39+
# Index operations
2940
create_index_templates_shared,
3041
delete_item_index_shared,
42+
index_alias_by_collection_id,
43+
index_by_collection_id,
44+
indices,
45+
46+
# Query operations
3147
apply_free_text_filter_shared,
3248
apply_intersects_filter_shared,
3349
populate_sort_shared,
50+
51+
# Mapping operations
3452
get_queryables_mapping_shared,
35-
)
53+
54+
# Document operations
55+
mk_item_id,
56+
mk_actions,
57+
58+
# Utility functions
59+
validate_refresh,
60+
)
61+
```

stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/database/__init__.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@
66
1. Index management functions for creating and deleting indices
77
2. Query building functions for constructing search queries
88
3. Mapping functions for working with Elasticsearch/OpenSearch mappings
9+
4. Document operations for working with documents
10+
5. Utility functions for database operations
911
1012
The database package is organized as follows:
1113
- index.py: Index management functions
1214
- query.py: Query building functions
1315
- mapping.py: Mapping functions
16+
- document.py: Document operations
17+
- utils.py: Utility functions
1418
1519
When adding new functionality to this package, consider:
1620
1. Will this code be used by both Elasticsearch and OpenSearch implementations?
@@ -24,19 +28,38 @@
2428
"""
2529

2630
# Re-export all functions for backward compatibility
27-
from .index import create_index_templates_shared, delete_item_index_shared
31+
from .document import mk_actions, mk_item_id
32+
from .index import (
33+
create_index_templates_shared,
34+
delete_item_index_shared,
35+
index_alias_by_collection_id,
36+
index_by_collection_id,
37+
indices,
38+
)
2839
from .mapping import get_queryables_mapping_shared
2940
from .query import (
3041
apply_free_text_filter_shared,
3142
apply_intersects_filter_shared,
3243
populate_sort_shared,
3344
)
45+
from .utils import validate_refresh
3446

3547
__all__ = [
48+
# Index operations
3649
"create_index_templates_shared",
3750
"delete_item_index_shared",
51+
"index_alias_by_collection_id",
52+
"index_by_collection_id",
53+
"indices",
54+
# Query operations
3855
"apply_free_text_filter_shared",
3956
"apply_intersects_filter_shared",
4057
"populate_sort_shared",
58+
# Mapping operations
4159
"get_queryables_mapping_shared",
60+
# Document operations
61+
"mk_item_id",
62+
"mk_actions",
63+
# Utility functions
64+
"validate_refresh",
4265
]
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"""Document operations for Elasticsearch/OpenSearch.
2+
3+
This module provides functions for working with documents in Elasticsearch/OpenSearch,
4+
including document ID generation and bulk action creation.
5+
"""
6+
7+
from typing import Any, Dict, List
8+
9+
from stac_fastapi.sfeos_helpers.database.index import index_alias_by_collection_id
10+
from stac_fastapi.types.stac import Item
11+
12+
13+
def mk_item_id(item_id: str, collection_id: str) -> str:
14+
"""Create the document id for an Item in Elasticsearch.
15+
16+
Args:
17+
item_id (str): The id of the Item.
18+
collection_id (str): The id of the Collection that the Item belongs to.
19+
20+
Returns:
21+
str: The document id for the Item, combining the Item id and the Collection id, separated by a `|` character.
22+
"""
23+
return f"{item_id}|{collection_id}"
24+
25+
26+
def mk_actions(collection_id: str, processed_items: List[Item]) -> List[Dict[str, Any]]:
27+
"""Create Elasticsearch bulk actions for a list of processed items.
28+
29+
Args:
30+
collection_id (str): The identifier for the collection the items belong to.
31+
processed_items (List[Item]): The list of processed items to be bulk indexed.
32+
33+
Returns:
34+
List[Dict[str, Union[str, Dict]]]: The list of bulk actions to be executed,
35+
each action being a dictionary with the following keys:
36+
- `_index`: the index to store the document in.
37+
- `_id`: the document's identifier.
38+
- `_source`: the source of the document.
39+
"""
40+
index_alias = index_alias_by_collection_id(collection_id)
41+
return [
42+
{
43+
"_index": index_alias,
44+
"_id": mk_item_id(item["id"], item["collection"]),
45+
"_source": item,
46+
}
47+
for item in processed_items
48+
]

stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/database/index.py

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,67 @@
33
This module provides functions for creating and managing indices in Elasticsearch/OpenSearch.
44
"""
55

6-
from typing import Any
6+
from functools import lru_cache
7+
from typing import Any, List, Optional
78

89
from stac_fastapi.sfeos_helpers.mappings import (
10+
_ES_INDEX_NAME_UNSUPPORTED_CHARS_TABLE,
911
COLLECTIONS_INDEX,
1012
ES_COLLECTIONS_MAPPINGS,
1113
ES_ITEMS_MAPPINGS,
1214
ES_ITEMS_SETTINGS,
15+
ITEM_INDICES,
1316
ITEMS_INDEX_PREFIX,
1417
)
15-
from stac_fastapi.sfeos_helpers.utilities import index_alias_by_collection_id
18+
19+
20+
@lru_cache(256)
21+
def index_by_collection_id(collection_id: str) -> str:
22+
"""
23+
Translate a collection id into an Elasticsearch index name.
24+
25+
Args:
26+
collection_id (str): The collection id to translate into an index name.
27+
28+
Returns:
29+
str: The index name derived from the collection id.
30+
"""
31+
cleaned = collection_id.translate(_ES_INDEX_NAME_UNSUPPORTED_CHARS_TABLE)
32+
return (
33+
f"{ITEMS_INDEX_PREFIX}{cleaned.lower()}_{collection_id.encode('utf-8').hex()}"
34+
)
35+
36+
37+
@lru_cache(256)
38+
def index_alias_by_collection_id(collection_id: str) -> str:
39+
"""
40+
Translate a collection id into an Elasticsearch index alias.
41+
42+
Args:
43+
collection_id (str): The collection id to translate into an index alias.
44+
45+
Returns:
46+
str: The index alias derived from the collection id.
47+
"""
48+
cleaned = collection_id.translate(_ES_INDEX_NAME_UNSUPPORTED_CHARS_TABLE)
49+
return f"{ITEMS_INDEX_PREFIX}{cleaned}"
50+
51+
52+
def indices(collection_ids: Optional[List[str]]) -> str:
53+
"""
54+
Get a comma-separated string of index names for a given list of collection ids.
55+
56+
Args:
57+
collection_ids: A list of collection ids.
58+
59+
Returns:
60+
A string of comma-separated index names. If `collection_ids` is empty, returns the default indices.
61+
"""
62+
return (
63+
",".join(map(index_alias_by_collection_id, collection_ids))
64+
if collection_ids
65+
else ITEM_INDICES
66+
)
1667

1768

1869
async def create_index_templates_shared(settings: Any) -> None:
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""Utility functions for database operations in Elasticsearch/OpenSearch.
2+
3+
This module provides utility functions for working with database operations
4+
in Elasticsearch/OpenSearch, such as parameter validation.
5+
"""
6+
7+
import logging
8+
from typing import Union
9+
10+
from stac_fastapi.core.utilities import get_bool_env
11+
12+
13+
def validate_refresh(value: Union[str, bool]) -> str:
14+
"""
15+
Validate the `refresh` parameter value.
16+
17+
Args:
18+
value (Union[str, bool]): The `refresh` parameter value, which can be a string or a boolean.
19+
20+
Returns:
21+
str: The validated value of the `refresh` parameter, which can be "true", "false", or "wait_for".
22+
"""
23+
logger = logging.getLogger(__name__)
24+
25+
# Handle boolean-like values using get_bool_env
26+
if isinstance(value, bool) or value in {
27+
"true",
28+
"false",
29+
"1",
30+
"0",
31+
"yes",
32+
"no",
33+
"y",
34+
"n",
35+
}:
36+
is_true = get_bool_env("DATABASE_REFRESH", default=value)
37+
return "true" if is_true else "false"
38+
39+
# Normalize to lowercase for case-insensitivity
40+
value = value.lower()
41+
42+
# Handle "wait_for" explicitly
43+
if value == "wait_for":
44+
return "wait_for"
45+
46+
# Log a warning for invalid values and default to "false"
47+
logger.warning(
48+
f"Invalid value for `refresh`: '{value}'. Expected 'true', 'false', or 'wait_for'. Defaulting to 'false'."
49+
)
50+
return "false"

0 commit comments

Comments
 (0)