Skip to content

Commit 5a66c64

Browse files
committed
update changelog, fixes
1 parent 1315ced commit 5a66c64

File tree

3 files changed

+64
-2
lines changed

3 files changed

+64
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
1616

1717
### Fixed
1818

19+
- Fixed filter parameter handling for GET `/collections-search` endpoint. Filter parameters (`filter` and `filter-lang`) are now properly passed through and processed.
20+
- Fixed `q` parameter in GET `/collections-search` endpoint to be converted to a list format, matching the behavior of the `/collections` endpoint for consistency.
21+
1922
### Removed
2023

2124
### Updated

stac_fastapi/core/stac_fastapi/core/extensions/collections_search.py

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@ class CollectionsSearchRequest(ExtendedSearch):
2222
query: Optional[
2323
str
2424
] = None # Legacy query extension (deprecated but still supported)
25+
filter_expr: Optional[str] = None
26+
filter_lang: Optional[str] = None
2527

2628

2729
def build_get_collections_search_doc(original_endpoint):
2830
"""Return a documented GET endpoint wrapper for /collections-search."""
2931

3032
async def documented_endpoint(
3133
request: Request,
32-
q: Optional[str] = Query(
34+
q: Optional[Union[str, List[str]]] = Query(
3335
None,
3436
description="Free text search query",
3537
),
@@ -76,9 +78,50 @@ async def documented_endpoint(
7678
),
7779
alias="fields[]",
7880
),
81+
filter: Optional[str] = Query(
82+
None,
83+
description=(
84+
"Structured filter expression in CQL2 JSON or CQL2-text format"
85+
),
86+
example='{"op": "=", "args": [{"property": "properties.category"}, "level2"]}',
87+
),
88+
filter_lang: Optional[str] = Query(
89+
None,
90+
description=(
91+
"Filter language. Must be 'cql2-json' or 'cql2-text' if specified"
92+
),
93+
example="cql2-json",
94+
),
7995
):
8096
# Delegate to original endpoint which reads from request.query_params
81-
return await original_endpoint(request)
97+
# But first, ensure the q parameter is properly handled as a list
98+
# since FastAPI extracts it from the URL when it's defined as a function parameter
99+
100+
# Create a mutable copy of query_params
101+
if hasattr(request, "_query_params"):
102+
query_params = dict(request._query_params)
103+
else:
104+
query_params = dict(request.query_params)
105+
106+
# Add q parameter back to query_params if it was provided
107+
# Convert to list format to match /collections behavior
108+
if q is not None:
109+
if isinstance(q, str):
110+
# Single string should become a list with one element
111+
query_params["q"] = [q]
112+
elif isinstance(q, list):
113+
# Already a list, use as-is
114+
query_params["q"] = q
115+
116+
# Temporarily replace request.query_params
117+
original_query_params = request.query_params
118+
request.query_params = query_params
119+
120+
try:
121+
return await original_endpoint(request)
122+
finally:
123+
# Restore original query_params
124+
request.query_params = original_query_params
82125

83126
documented_endpoint.__name__ = original_endpoint.__name__
84127
return documented_endpoint
@@ -95,6 +138,8 @@ async def documented_post_endpoint(
95138
"Search parameters for collections.\n\n"
96139
"- `q`: Free text search query (string or list of strings)\n"
97140
"- `query`: Additional filtering expressed as a string (legacy support)\n"
141+
"- `filter`: Structured filter expression in CQL2 JSON or CQL2-text format\n"
142+
"- `filter_lang`: Filter language. Must be 'cql2-json' or 'cql2-text' if specified\n"
98143
"- `limit`: Maximum number of results to return (default: 10)\n"
99144
"- `token`: Pagination token for the next page of results\n"
100145
"- `bbox`: Bounding box [minx, miny, maxx, maxy] or [minx, miny, minz, maxx, maxy, maxz]\n"
@@ -105,6 +150,11 @@ async def documented_post_endpoint(
105150
example={
106151
"q": "landsat",
107152
"query": "platform=landsat AND collection_category=level2",
153+
"filter": {
154+
"op": "=",
155+
"args": [{"property": "properties.category"}, "level2"],
156+
},
157+
"filter_lang": "cql2-json",
108158
"limit": 10,
109159
"token": "next-page-token",
110160
"bbox": [-180, -90, 180, 90],
@@ -243,6 +293,14 @@ async def collections_search_get_endpoint(
243293
sortby = sortby_str.split(",")
244294
params["sortby"] = sortby
245295

296+
# Handle filter parameter mapping (fixed for collections-search)
297+
if "filter" in params:
298+
params["filter_expr"] = params.pop("filter")
299+
300+
# Handle filter-lang parameter mapping (fixed for collections-search)
301+
if "filter-lang" in params:
302+
params["filter_lang"] = params.pop("filter-lang")
303+
246304
collections = await self.client.all_collections(request=request, **params)
247305
return collections
248306

stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/app.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@
198198
FieldsConformanceClasses.COLLECTIONS,
199199
],
200200
)
201+
extensions.append(collection_search_ext)
201202
extensions.append(collections_search_endpoint_ext)
202203

203204

0 commit comments

Comments
 (0)