Skip to content

Commit 49cfd54

Browse files
Yuri ZmytrakovYuri Zmytrakov
authored andcommitted
first commit
1 parent 375bb8d commit 49cfd54

File tree

1 file changed

+38
-26
lines changed

1 file changed

+38
-26
lines changed

stac_fastapi/opensearch/stac_fastapi/opensearch/database_logic.py

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from base64 import urlsafe_b64decode, urlsafe_b64encode
66
from collections.abc import Iterable
77
from copy import deepcopy
8+
from dataclasses import dataclass
89
from typing import Any, Dict, List, Optional, Tuple, Type
910

1011
import attr
@@ -74,6 +75,36 @@
7475
logger = logging.getLogger(__name__)
7576

7677

78+
@dataclass
79+
class GeoShapeNode:
80+
geometry: "GeometryNode"
81+
82+
83+
@dataclass
84+
class GeometryNode:
85+
shape: "ShapeNode"
86+
relation: str
87+
88+
89+
@dataclass
90+
class ShapeNode:
91+
type: str
92+
coordinates: List[List[List[float]]]
93+
94+
95+
def analyze_bbox_query(node) -> dict:
96+
"""Analyze and build bbox query"""
97+
if isinstance(node, GeoShapeNode):
98+
return analyze_bbox_query(node.geometry)
99+
elif isinstance(node, GeometryNode):
100+
shape_filter = analyze_bbox_query(node.shape)
101+
return {"shape": shape_filter, "relation": node.relation}
102+
elif isinstance(node, ShapeNode):
103+
if node.type == "polygon":
104+
return {"type": node.type, "coordinates": node.coordinates}
105+
return {}
106+
107+
77108
async def create_index_templates() -> None:
78109
"""
79110
Create index templates for the Collection and Item indices.
@@ -595,34 +626,15 @@ def apply_datetime_filter(
595626

596627
@staticmethod
597628
def apply_bbox_filter(search: Search, bbox: List):
598-
"""Filter search results based on bounding box.
629+
"""Filter search results based on bounding box using AST analysis pattern."""
630+
polygon_coordinates = bbox2polygon(*bbox)
599631

600-
Args:
601-
search (Search): The search object to apply the filter to.
602-
bbox (List): The bounding box coordinates, represented as a list of four values [minx, miny, maxx, maxy].
603-
604-
Returns:
605-
search (Search): The search object with the bounding box filter applied.
632+
shape_node = ShapeNode(type="polygon", coordinates=polygon_coordinates)
633+
geometry_node = GeometryNode(shape=shape_node, relation="intersects")
634+
geo_shape_node = GeoShapeNode(geometry=geometry_node)
606635

607-
Notes:
608-
The bounding box is transformed into a polygon using the `bbox2polygon` function and
609-
a geo_shape filter is added to the search object, set to intersect with the specified polygon.
610-
"""
611-
return search.filter(
612-
Q(
613-
{
614-
"geo_shape": {
615-
"geometry": {
616-
"shape": {
617-
"type": "polygon",
618-
"coordinates": bbox2polygon(*bbox),
619-
},
620-
"relation": "intersects",
621-
}
622-
}
623-
}
624-
)
625-
)
636+
bbox_query_dict = analyze_bbox_query(geo_shape_node)
637+
return search.filter(Q("geo_shape", geometry=bbox_query_dict))
626638

627639
@staticmethod
628640
def apply_intersects_filter(

0 commit comments

Comments
 (0)