3
3
import logging
4
4
from datetime import datetime as datetime_type
5
5
from datetime import timezone
6
- from typing import List , Optional , Type , Union
6
+ from typing import Any , Dict , List , Optional , Type , Union
7
7
from urllib .parse import urljoin
8
8
9
9
import attr
21
21
from stac_fastapi .elasticsearch .models .links import PagingLinks
22
22
from stac_fastapi .elasticsearch .serializers import CollectionSerializer , ItemSerializer
23
23
from stac_fastapi .elasticsearch .session import Session
24
+ from stac_fastapi .extensions .core .filter .request import FilterLang
24
25
from stac_fastapi .extensions .third_party .bulk_transactions import (
25
26
BaseBulkTransactionsClient ,
26
27
Items ,
27
28
)
28
29
from stac_fastapi .types import stac as stac_types
29
- from stac_fastapi .types .core import AsyncBaseCoreClient , AsyncBaseTransactionsClient
30
+ from stac_fastapi .types .core import (
31
+ AsyncBaseCoreClient ,
32
+ AsyncBaseFiltersClient ,
33
+ AsyncBaseTransactionsClient ,
34
+ )
30
35
from stac_fastapi .types .links import CollectionLinks
31
36
from stac_fastapi .types .stac import Collection , Collections , Item , ItemCollection
32
37
@@ -172,6 +177,8 @@ async def get_search(
172
177
token : Optional [str ] = None ,
173
178
fields : Optional [List [str ]] = None ,
174
179
sortby : Optional [str ] = None ,
180
+ # filter: Optional[str] = None, # todo: requires fastapi > 2.3 unreleased
181
+ # filter_lang: Optional[str] = None, # todo: requires fastapi > 2.3 unreleased
175
182
** kwargs ,
176
183
) -> ItemCollection :
177
184
"""GET search catalog."""
@@ -183,8 +190,10 @@ async def get_search(
183
190
"token" : token ,
184
191
"query" : json .loads (query ) if query else query ,
185
192
}
193
+
186
194
if datetime :
187
195
base_args ["datetime" ] = datetime
196
+
188
197
if sortby :
189
198
# https://github.com/radiantearth/stac-spec/tree/master/api-spec/extensions/sort#http-get-or-post-form
190
199
sort_param = []
@@ -197,6 +206,13 @@ async def get_search(
197
206
)
198
207
base_args ["sortby" ] = sort_param
199
208
209
+ # todo: requires fastapi > 2.3 unreleased
210
+ # if filter:
211
+ # if filter_lang == "cql2-text":
212
+ # base_args["filter-lang"] = "cql2-json"
213
+ # base_args["filter"] = orjson.loads(to_cql2(parse_cql2_text(filter)))
214
+ # print(f'>>> {base_args["filter"]}')
215
+
200
216
# if fields:
201
217
# includes = set()
202
218
# excludes = set()
@@ -264,6 +280,15 @@ async def post_search(
264
280
search = search , op = op , field = field , value = value
265
281
)
266
282
283
+ filter_lang = getattr (search_request , "filter_lang" , None )
284
+
285
+ if hasattr (search_request , "filter" ):
286
+ cql2_filter = getattr (search_request , "filter" , None )
287
+ if filter_lang in [None , FilterLang .cql2_json ]:
288
+ search = self .database .apply_cql2_filter (search , cql2_filter )
289
+ else :
290
+ raise Exception ("CQL2-Text is not supported with POST" )
291
+
267
292
sort = None
268
293
if search_request .sortby :
269
294
sort = self .database .populate_sort (search_request .sortby )
@@ -455,3 +480,68 @@ def bulk_item_insert(
455
480
)
456
481
457
482
return f"Successfully added { len (processed_items )} Items."
483
+
484
+
485
+ @attr .s
486
+ class EsAsyncBaseFiltersClient (AsyncBaseFiltersClient ):
487
+ """Defines a pattern for implementing the STAC filter extension."""
488
+
489
+ # todo: use the ES _mapping endpoint to dynamically find what fields exist
490
+ async def get_queryables (
491
+ self , collection_id : Optional [str ] = None , ** kwargs
492
+ ) -> Dict [str , Any ]:
493
+ """Get the queryables available for the given collection_id.
494
+
495
+ If collection_id is None, returns the intersection of all
496
+ queryables over all collections.
497
+
498
+ This base implementation returns a blank queryable schema. This is not allowed
499
+ under OGC CQL but it is allowed by the STAC API Filter Extension
500
+
501
+ https://github.com/radiantearth/stac-api-spec/tree/master/fragments/filter#queryables
502
+ """
503
+ return {
504
+ "$schema" : "https://json-schema.org/draft/2019-09/schema" ,
505
+ "$id" : "https://stac-api.example.com/queryables" ,
506
+ "type" : "object" ,
507
+ "title" : "Queryables for Example STAC API" ,
508
+ "description" : "Queryable names for the example STAC API Item Search filter." ,
509
+ "properties" : {
510
+ "id" : {
511
+ "description" : "ID" ,
512
+ "$ref" : "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json#/id" ,
513
+ },
514
+ "collection" : {
515
+ "description" : "Collection" ,
516
+ "$ref" : "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json#/collection" ,
517
+ },
518
+ "geometry" : {
519
+ "description" : "Geometry" ,
520
+ "$ref" : "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/item.json#/geometry" ,
521
+ },
522
+ "datetime" : {
523
+ "description" : "Acquisition Timestamp" ,
524
+ "$ref" : "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/datetime.json#/properties/datetime" ,
525
+ },
526
+ "created" : {
527
+ "description" : "Creation Timestamp" ,
528
+ "$ref" : "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/datetime.json#/properties/created" ,
529
+ },
530
+ "updated" : {
531
+ "description" : "Creation Timestamp" ,
532
+ "$ref" : "https://schemas.stacspec.org/v1.0.0/item-spec/json-schema/datetime.json#/properties/updated" ,
533
+ },
534
+ "cloud_cover" : {
535
+ "description" : "Cloud Cover" ,
536
+ "$ref" : "https://stac-extensions.github.io/eo/v1.0.0/schema.json#/definitions/fields/properties/eo:cloud_cover" ,
537
+ },
538
+ "cloud_shadow_percentage" : {
539
+ "description" : "Cloud Shadow Percentage" ,
540
+ "title" : "Cloud Shadow Percentage" ,
541
+ "type" : "number" ,
542
+ "minimum" : 0 ,
543
+ "maximum" : 100 ,
544
+ },
545
+ },
546
+ "additionalProperties" : True ,
547
+ }
0 commit comments