Skip to content

Commit df6a32d

Browse files
committed
collection search get sort
1 parent 56af26d commit df6a32d

File tree

4 files changed

+72
-8
lines changed

4 files changed

+72
-8
lines changed

stac_fastapi/core/stac_fastapi/core/core.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,9 @@ async def landing_page(self, **kwargs) -> stac_types.LandingPage:
224224

225225
return landing_page
226226

227-
async def all_collections(self, **kwargs) -> stac_types.Collections:
227+
async def all_collections(
228+
self, sortby: Optional[str] = None, **kwargs
229+
) -> stac_types.Collections:
228230
"""Read all collections from the database.
229231
230232
Args:
@@ -238,8 +240,23 @@ async def all_collections(self, **kwargs) -> stac_types.Collections:
238240
limit = int(request.query_params.get("limit", os.getenv("STAC_ITEM_LIMIT", 10)))
239241
token = request.query_params.get("token")
240242

243+
sort = None
244+
if sortby:
245+
parsed_sort = []
246+
for raw in sortby:
247+
if not isinstance(raw, str):
248+
continue
249+
s = raw.strip()
250+
if not s:
251+
continue
252+
direction = "desc" if s[0] == "-" else "asc"
253+
field = s[1:] if s and s[0] in "+-" else s
254+
parsed_sort.append({"field": field, "direction": direction})
255+
if parsed_sort:
256+
sort = parsed_sort
257+
241258
collections, next_token = await self.database.get_all_collections(
242-
token=token, limit=limit, request=request
259+
token=token, limit=limit, request=request, sort=sort
243260
)
244261

245262
links = [

stac_fastapi/elasticsearch/stac_fastapi/elasticsearch/database_logic.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,13 +170,19 @@ def __attrs_post_init__(self):
170170
"""CORE LOGIC"""
171171

172172
async def get_all_collections(
173-
self, token: Optional[str], limit: int, request: Request
173+
self,
174+
token: Optional[str],
175+
limit: int,
176+
request: Request,
177+
sort: Optional[List[Dict[str, Any]]] = None,
174178
) -> Tuple[List[Dict[str, Any]], Optional[str]]:
175-
"""Retrieve a list of all collections from Elasticsearch, supporting pagination.
179+
"""Retrieve a list of collections from Elasticsearch, supporting pagination.
176180
177181
Args:
178182
token (Optional[str]): The pagination token.
179183
limit (int): The number of results to return.
184+
request (Request): The FastAPI request object.
185+
sort (Optional[List[Dict[str, Any]]]): Optional sort parameter from the request.
180186
181187
Returns:
182188
A tuple of (collections, next pagination token if any).
@@ -185,10 +191,21 @@ async def get_all_collections(
185191
if token:
186192
search_after = [token]
187193

194+
formatted_sort = None
195+
if sort:
196+
formatted_sort = {}
197+
for item in sort:
198+
field = item.get("field")
199+
direction = item.get("direction", "asc")
200+
if field:
201+
formatted_sort[field] = {"order": direction}
202+
# Always include id as a secondary sort to ensure consistent pagination
203+
formatted_sort.setdefault("id", {"order": "asc"})
204+
188205
response = await self.client.search(
189206
index=COLLECTIONS_INDEX,
190207
body={
191-
"sort": [{"id": {"order": "asc"}}],
208+
"sort": formatted_sort or DEFAULT_SORT,
192209
"size": limit,
193210
**({"search_after": search_after} if search_after is not None else {}),
194211
},

stac_fastapi/opensearch/stac_fastapi/opensearch/database_logic.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,20 +153,39 @@ def __attrs_post_init__(self):
153153
"""CORE LOGIC"""
154154

155155
async def get_all_collections(
156-
self, token: Optional[str], limit: int, request: Request
156+
self,
157+
token: Optional[str],
158+
limit: int,
159+
request: Request,
160+
sort: Optional[List[Dict[str, Any]]] = None,
157161
) -> Tuple[List[Dict[str, Any]], Optional[str]]:
158162
"""
159-
Retrieve a list of all collections from Opensearch, supporting pagination.
163+
Retrieve a list of collections from Opensearch, supporting pagination.
160164
161165
Args:
162166
token (Optional[str]): The pagination token.
163167
limit (int): The number of results to return.
168+
request (Request): The FastAPI request object.
169+
sort (Optional[List[Dict[str, Any]]]): Optional sort parameter from the request.
164170
165171
Returns:
166172
A tuple of (collections, next pagination token if any).
167173
"""
174+
formatted_sort = []
175+
if sort:
176+
for item in sort:
177+
field = item.get("field")
178+
direction = item.get("direction", "asc")
179+
if field:
180+
formatted_sort.append({field: {"order": direction}})
181+
# Always include id as a secondary sort to ensure consistent pagination
182+
if not any("id" in item for item in formatted_sort):
183+
formatted_sort.append({"id": {"order": "asc"}})
184+
else:
185+
formatted_sort = [{"id": {"order": "asc"}}]
186+
168187
search_body = {
169-
"sort": [{"id": {"order": "asc"}}],
188+
"sort": formatted_sort,
170189
"size": limit,
171190
}
172191

stac_fastapi/sfeos_helpers/stac_fastapi/sfeos_helpers/mappings.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,17 @@ class Geometry(Protocol): # noqa
160160
"dynamic_templates": ES_MAPPINGS_DYNAMIC_TEMPLATES,
161161
"properties": {
162162
"id": {"type": "keyword"},
163+
# "bbox_shape": {"type": "geo_shape"}, # Only this is used for spatial queries
164+
# "extent": {
165+
# "properties": {"temporal": {"properties": {"interval": {"type": "date"}}}}
166+
# },
167+
# "properties": {
168+
# "properties": {
169+
# "datetime": {"type": "date"},
170+
# "start_datetime": {"type": "date"},
171+
# "end_datetime": {"type": "date"},
172+
# }
173+
# },
163174
"extent.spatial.bbox": {"type": "long"},
164175
"extent.temporal.interval": {"type": "date"},
165176
"providers": {"type": "object", "enabled": False},

0 commit comments

Comments
 (0)