Skip to content

Commit 783e395

Browse files
committed
created shared datetime fiter fn
1 parent 1924950 commit 783e395

File tree

4 files changed

+75
-105
lines changed

4 files changed

+75
-105
lines changed

stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/database_logic.py

Lines changed: 6 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@
3030
from stac_fastapi.sfeos_helpers import filter as filter_module
3131
from stac_fastapi.sfeos_helpers.database import (
3232
apply_collections_bbox_filter_shared,
33+
apply_collections_datetime_filter_shared,
3334
apply_free_text_filter_shared,
3435
apply_intersects_filter_shared,
3536
create_index_templates_shared,
3637
delete_item_index_shared,
3738
get_queryables_mapping_shared,
3839
index_alias_by_collection_id,
39-
index_by_collection_id,
4040
mk_actions,
4141
mk_item_id,
4242
populate_sort_shared,
@@ -100,26 +100,6 @@ async def create_collection_index() -> None:
100100
await client.close()
101101

102102

103-
async def create_item_index(collection_id: str):
104-
"""
105-
Create the index for Items. The settings of the index template will be used implicitly.
106-
107-
Args:
108-
collection_id (str): Collection identifier.
109-
110-
Returns:
111-
None
112-
113-
"""
114-
client = AsyncElasticsearchSettings().create_client
115-
116-
await client.options(ignore_status=400).indices.create(
117-
index=f"{index_by_collection_id(collection_id)}-000001",
118-
body={"aliases": {index_alias_by_collection_id(collection_id): {}}},
119-
)
120-
await client.close()
121-
122-
123103
async def delete_item_index(collection_id: str):
124104
"""Delete the index for items in a collection.
125105
@@ -322,12 +302,10 @@ async def get_all_collections(
322302
if bbox_filter:
323303
query_parts.append(bbox_filter)
324304

325-
# Combine all query parts with AND logic if there are multiple
326-
datetime_filter = None
327-
if datetime:
328-
datetime_filter = self._apply_collection_datetime_filter(datetime)
329-
if datetime_filter:
330-
query_parts.append(datetime_filter)
305+
# Apply datetime filter if provided
306+
datetime_filter = apply_collections_datetime_filter_shared(datetime)
307+
if datetime_filter:
308+
query_parts.append(datetime_filter)
331309

332310
# Combine all query parts with AND logic
333311
if query_parts:
@@ -386,41 +364,6 @@ async def get_all_collections(
386364

387365
return collections, next_token, matched
388366

389-
@staticmethod
390-
def _apply_collection_datetime_filter(
391-
datetime_str: Optional[str],
392-
) -> Optional[Dict[str, Any]]:
393-
"""Create a temporal filter for collections based on their extent."""
394-
if not datetime_str:
395-
return None
396-
397-
# Parse the datetime string into start and end
398-
if "/" in datetime_str:
399-
start, end = datetime_str.split("/")
400-
# Replace open-ended ranges with concrete dates
401-
if start == "..":
402-
# For open-ended start, use a very early date
403-
start = "1800-01-01T00:00:00Z"
404-
if end == "..":
405-
# For open-ended end, use a far future date
406-
end = "2999-12-31T23:59:59Z"
407-
else:
408-
# If it's just a single date, use it for both start and end
409-
start = end = datetime_str
410-
411-
return {
412-
"bool": {
413-
"must": [
414-
# Check if any date in the array is less than or equal to the query end date
415-
# This will match if the collection's start date is before or equal to the query end date
416-
{"range": {"extent.temporal.interval": {"lte": end}}},
417-
# Check if any date in the array is greater than or equal to the query start date
418-
# This will match if the collection's end date is after or equal to the query start date
419-
{"range": {"extent.temporal.interval": {"gte": start}}},
420-
]
421-
}
422-
}
423-
424367
async def get_one_item(self, collection_id: str, item_id: str) -> Dict:
425368
"""Retrieve a single item from the database.
426369
@@ -1388,7 +1331,7 @@ async def create_collection(self, collection: Collection, **kwargs: Any):
13881331
None
13891332
13901333
Notes:
1391-
A new index is created for the items in the Collection using the `create_item_index` function.
1334+
A new index is created for the items in the Collection if the index insertion strategy requires it.
13921335
"""
13931336
collection_id = collection["id"]
13941337

stac_fastapi/opensearch/stac_fastapi/opensearch/database_logic.py

Lines changed: 6 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from stac_fastapi.sfeos_helpers import filter as filter_module
3131
from stac_fastapi.sfeos_helpers.database import (
3232
apply_collections_bbox_filter_shared,
33+
apply_collections_datetime_filter_shared,
3334
apply_free_text_filter_shared,
3435
apply_intersects_filter_shared,
3536
create_index_templates_shared,
@@ -306,12 +307,10 @@ async def get_all_collections(
306307
if bbox_filter:
307308
query_parts.append(bbox_filter)
308309

309-
# Combine all query parts with AND logic if there are multiple
310-
datetime_filter = None
311-
if datetime:
312-
datetime_filter = self._apply_collection_datetime_filter(datetime)
313-
if datetime_filter:
314-
query_parts.append(datetime_filter)
310+
# Apply datetime filter if provided
311+
datetime_filter = apply_collections_datetime_filter_shared(datetime)
312+
if datetime_filter:
313+
query_parts.append(datetime_filter)
315314

316315
# Combine all query parts with AND logic
317316
if query_parts:
@@ -456,41 +455,6 @@ def apply_free_text_filter(search: Search, free_text_queries: Optional[List[str]
456455
search=search, free_text_queries=free_text_queries
457456
)
458457

459-
@staticmethod
460-
def _apply_collection_datetime_filter(
461-
datetime_str: Optional[str],
462-
) -> Optional[Dict[str, Any]]:
463-
"""Create a temporal filter for collections based on their extent."""
464-
if not datetime_str:
465-
return None
466-
467-
# Parse the datetime string into start and end
468-
if "/" in datetime_str:
469-
start, end = datetime_str.split("/")
470-
# Replace open-ended ranges with concrete dates
471-
if start == "..":
472-
# For open-ended start, use a very early date
473-
start = "1800-01-01T00:00:00Z"
474-
if end == "..":
475-
# For open-ended end, use a far future date
476-
end = "2999-12-31T23:59:59Z"
477-
else:
478-
# If it's just a single date, use it for both start and end
479-
start = end = datetime_str
480-
481-
return {
482-
"bool": {
483-
"must": [
484-
# Check if any date in the array is less than or equal to the query end date
485-
# This will match if the collection's start date is before or equal to the query end date
486-
{"range": {"extent.temporal.interval": {"lte": end}}},
487-
# Check if any date in the array is greater than or equal to the query start date
488-
# This will match if the collection's end date is after or equal to the query start date
489-
{"range": {"extent.temporal.interval": {"gte": start}}},
490-
]
491-
}
492-
}
493-
494458
@staticmethod
495459
def apply_datetime_filter(
496460
search: Search, datetime: Optional[str]
@@ -1358,7 +1322,7 @@ async def create_collection(self, collection: Collection, **kwargs: Any):
13581322
ConflictError: If a Collection with the same id already exists in the database.
13591323
13601324
Notes:
1361-
A new index is created for the items in the Collection using the `create_item_index` function.
1325+
A new index is created for the items in the Collection if the index insertion strategy requires it.
13621326
"""
13631327
collection_id = collection["id"]
13641328

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
from .mapping import get_queryables_mapping_shared
4444
from .query import (
4545
apply_collections_bbox_filter_shared,
46+
apply_collections_datetime_filter_shared,
4647
apply_free_text_filter_shared,
4748
apply_intersects_filter_shared,
4849
populate_sort_shared,
@@ -61,6 +62,7 @@
6162
"apply_free_text_filter_shared",
6263
"apply_intersects_filter_shared",
6364
"apply_collections_bbox_filter_shared",
65+
"apply_collections_datetime_filter_shared",
6466
"populate_sort_shared",
6567
# Mapping operations
6668
"get_queryables_mapping_shared",

stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/database/query.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,67 @@ def apply_intersects_filter_shared(
6868
}
6969

7070

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+
71132
def apply_collections_bbox_filter_shared(
72133
bbox: Union[str, List[float], None]
73134
) -> Optional[Dict[str, Dict]]:

0 commit comments

Comments
 (0)