Skip to content

Commit 67e1c4c

Browse files
committed
move to_es filter update to sfeos_helpers
1 parent 14d88b2 commit 67e1c4c

File tree

2 files changed

+14
-116
lines changed
  • stac_fastapi
    • core/stac_fastapi/core/extensions
    • sfeos_helpers/stac_fastapi/sfeos_helpers

2 files changed

+14
-116
lines changed

stac_fastapi/core/stac_fastapi/core/extensions/filter.py

Lines changed: 0 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -147,111 +147,3 @@ def to_es_field(queryables_mapping: Dict[str, Any], field: str) -> str:
147147
str: The mapped field name suitable for Elasticsearch queries.
148148
"""
149149
return queryables_mapping.get(field, field)
150-
151-
152-
def to_es(queryables_mapping: Dict[str, Any], query: Dict[str, Any]) -> Dict[str, Any]:
153-
"""
154-
Transform a simplified CQL2 query structure to an Elasticsearch compatible query DSL.
155-
156-
Args:
157-
query (Dict[str, Any]): The query dictionary containing 'op' and 'args'.
158-
159-
Returns:
160-
Dict[str, Any]: The corresponding Elasticsearch query in the form of a dictionary.
161-
"""
162-
if query["op"] in [LogicalOp.AND, LogicalOp.OR, LogicalOp.NOT]:
163-
bool_type = {
164-
LogicalOp.AND: "must",
165-
LogicalOp.OR: "should",
166-
LogicalOp.NOT: "must_not",
167-
}[query["op"]]
168-
return {
169-
"bool": {
170-
bool_type: [
171-
to_es(queryables_mapping, sub_query) for sub_query in query["args"]
172-
]
173-
}
174-
}
175-
176-
elif query["op"] in [
177-
ComparisonOp.EQ,
178-
ComparisonOp.NEQ,
179-
ComparisonOp.LT,
180-
ComparisonOp.LTE,
181-
ComparisonOp.GT,
182-
ComparisonOp.GTE,
183-
]:
184-
range_op = {
185-
ComparisonOp.LT: "lt",
186-
ComparisonOp.LTE: "lte",
187-
ComparisonOp.GT: "gt",
188-
ComparisonOp.GTE: "gte",
189-
}
190-
191-
field = to_es_field(queryables_mapping, query["args"][0]["property"])
192-
value = query["args"][1]
193-
if isinstance(value, dict) and "timestamp" in value:
194-
value = value["timestamp"]
195-
if query["op"] == ComparisonOp.EQ:
196-
return {"range": {field: {"gte": value, "lte": value}}}
197-
elif query["op"] == ComparisonOp.NEQ:
198-
return {
199-
"bool": {
200-
"must_not": [{"range": {field: {"gte": value, "lte": value}}}]
201-
}
202-
}
203-
else:
204-
return {"range": {field: {range_op[query["op"]]: value}}}
205-
else:
206-
if query["op"] == ComparisonOp.EQ:
207-
return {"term": {field: value}}
208-
elif query["op"] == ComparisonOp.NEQ:
209-
return {"bool": {"must_not": [{"term": {field: value}}]}}
210-
else:
211-
return {"range": {field: {range_op[query["op"]]: value}}}
212-
213-
elif query["op"] == ComparisonOp.IS_NULL:
214-
field = to_es_field(queryables_mapping, query["args"][0]["property"])
215-
return {"bool": {"must_not": {"exists": {"field": field}}}}
216-
217-
elif query["op"] == AdvancedComparisonOp.BETWEEN:
218-
field = to_es_field(queryables_mapping, query["args"][0]["property"])
219-
gte, lte = query["args"][1], query["args"][2]
220-
if isinstance(gte, dict) and "timestamp" in gte:
221-
gte = gte["timestamp"]
222-
if isinstance(lte, dict) and "timestamp" in lte:
223-
lte = lte["timestamp"]
224-
return {"range": {field: {"gte": gte, "lte": lte}}}
225-
226-
elif query["op"] == AdvancedComparisonOp.IN:
227-
field = to_es_field(queryables_mapping, query["args"][0]["property"])
228-
values = query["args"][1]
229-
if not isinstance(values, list):
230-
raise ValueError(f"Arg {values} is not a list")
231-
return {"terms": {field: values}}
232-
233-
elif query["op"] == AdvancedComparisonOp.LIKE:
234-
field = to_es_field(queryables_mapping, query["args"][0]["property"])
235-
pattern = cql2_like_to_es(query["args"][1])
236-
return {"wildcard": {field: {"value": pattern, "case_insensitive": True}}}
237-
238-
elif query["op"] in [
239-
SpatialOp.S_INTERSECTS,
240-
SpatialOp.S_CONTAINS,
241-
SpatialOp.S_WITHIN,
242-
SpatialOp.S_DISJOINT,
243-
]:
244-
field = to_es_field(queryables_mapping, query["args"][0]["property"])
245-
geometry = query["args"][1]
246-
247-
relation_mapping = {
248-
SpatialOp.S_INTERSECTS: "intersects",
249-
SpatialOp.S_CONTAINS: "contains",
250-
SpatialOp.S_WITHIN: "within",
251-
SpatialOp.S_DISJOINT: "disjoint",
252-
}
253-
254-
relation = relation_mapping[query["op"]]
255-
return {"geo_shape": {field: {"shape": geometry, "relation": relation}}}
256-
257-
return {}

stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/filter.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from .mappings import ES_MAPPING_TYPE_TO_JSON
2121

2222

23-
def to_es(query: Dict[str, Any]) -> Dict[str, Any]:
23+
def to_es(queryables_mapping: Dict[str, Any], query: Dict[str, Any]) -> Dict[str, Any]:
2424
"""
2525
Transform a simplified CQL2 query structure to an Elasticsearch compatible query DSL.
2626
@@ -36,7 +36,13 @@ def to_es(query: Dict[str, Any]) -> Dict[str, Any]:
3636
LogicalOp.OR: "should",
3737
LogicalOp.NOT: "must_not",
3838
}[query["op"]]
39-
return {"bool": {bool_type: [to_es(sub_query) for sub_query in query["args"]]}}
39+
return {
40+
"bool": {
41+
bool_type: [
42+
to_es(queryables_mapping, sub_query) for sub_query in query["args"]
43+
]
44+
}
45+
}
4046

4147
elif query["op"] in [
4248
ComparisonOp.EQ,
@@ -53,7 +59,7 @@ def to_es(query: Dict[str, Any]) -> Dict[str, Any]:
5359
ComparisonOp.GTE: "gte",
5460
}
5561

56-
field = to_es_field(query["args"][0]["property"])
62+
field = to_es_field(queryables_mapping, query["args"][0]["property"])
5763
value = query["args"][1]
5864
if isinstance(value, dict) and "timestamp" in value:
5965
value = value["timestamp"]
@@ -76,11 +82,11 @@ def to_es(query: Dict[str, Any]) -> Dict[str, Any]:
7682
return {"range": {field: {range_op[query["op"]]: value}}}
7783

7884
elif query["op"] == ComparisonOp.IS_NULL:
79-
field = to_es_field(query["args"][0]["property"])
85+
field = to_es_field(queryables_mapping, query["args"][0]["property"])
8086
return {"bool": {"must_not": {"exists": {"field": field}}}}
8187

8288
elif query["op"] == AdvancedComparisonOp.BETWEEN:
83-
field = to_es_field(query["args"][0]["property"])
89+
field = to_es_field(queryables_mapping, query["args"][0]["property"])
8490
gte, lte = query["args"][1], query["args"][2]
8591
if isinstance(gte, dict) and "timestamp" in gte:
8692
gte = gte["timestamp"]
@@ -89,14 +95,14 @@ def to_es(query: Dict[str, Any]) -> Dict[str, Any]:
8995
return {"range": {field: {"gte": gte, "lte": lte}}}
9096

9197
elif query["op"] == AdvancedComparisonOp.IN:
92-
field = to_es_field(query["args"][0]["property"])
98+
field = to_es_field(queryables_mapping, query["args"][0]["property"])
9399
values = query["args"][1]
94100
if not isinstance(values, list):
95101
raise ValueError(f"Arg {values} is not a list")
96102
return {"terms": {field: values}}
97103

98104
elif query["op"] == AdvancedComparisonOp.LIKE:
99-
field = to_es_field(query["args"][0]["property"])
105+
field = to_es_field(queryables_mapping, query["args"][0]["property"])
100106
pattern = cql2_like_to_es(query["args"][1])
101107
return {"wildcard": {field: {"value": pattern, "case_insensitive": True}}}
102108

@@ -106,7 +112,7 @@ def to_es(query: Dict[str, Any]) -> Dict[str, Any]:
106112
SpatialOp.S_WITHIN,
107113
SpatialOp.S_DISJOINT,
108114
]:
109-
field = to_es_field(query["args"][0]["property"])
115+
field = to_es_field(queryables_mapping, query["args"][0]["property"])
110116
geometry = query["args"][1]
111117

112118
relation_mapping = {

0 commit comments

Comments
 (0)