1616
1717from stac_fastapi .core .base_database_logic import BaseDatabaseLogic
1818from stac_fastapi .core .serializers import CollectionSerializer , ItemSerializer
19- from stac_fastapi .core .utilities import bbox2polygon , get_max_limit
19+ from stac_fastapi .core .utilities import bbox2polygon , get_bool_env , get_max_limit
2020from stac_fastapi .extensions .core .transaction .request import (
2121 PartialCollection ,
2222 PartialItem ,
@@ -301,21 +301,118 @@ def apply_datetime_filter(
301301 if not datetime_search :
302302 return search , datetime_search
303303
304- if "eq" in datetime_search :
305- # For exact matches, include:
306- # 1. Items with matching exact datetime
307- # 2. Items with datetime:null where the time falls within their range
308- should = [
309- Q (
310- "bool" ,
311- filter = [
312- Q ("exists" , field = "properties.datetime" ),
313- Q ("term" , ** {"properties__datetime" : datetime_search ["eq" ]}),
314- ],
315- ),
316- Q (
304+ # USE_DATETIME env var
305+ # True: Search by datetime, if null search by start/end datetime
306+ # False: Always search only by start/end datetime
307+ USE_DATETIME = get_bool_env ("USE_DATETIME" , default = True )
308+
309+ if USE_DATETIME :
310+ if "eq" in datetime_search :
311+ # For exact matches, include:
312+ # 1. Items with matching exact datetime
313+ # 2. Items with datetime:null where the time falls within their range
314+ should = [
315+ Q (
316+ "bool" ,
317+ filter = [
318+ Q ("exists" , field = "properties.datetime" ),
319+ Q (
320+ "term" ,
321+ ** {"properties__datetime" : datetime_search ["eq" ]},
322+ ),
323+ ],
324+ ),
325+ Q (
326+ "bool" ,
327+ filter = [
328+ Q (
329+ "bool" ,
330+ should = [
331+ Q (
332+ "bool" ,
333+ must_not = [
334+ Q ("exists" , field = "properties.datetime" )
335+ ],
336+ ),
337+ Q ("term" , ** {"properties__datetime" : None }),
338+ ],
339+ minimum_should_match = 1 ,
340+ ),
341+ Q ("exists" , field = "properties.start_datetime" ),
342+ Q ("exists" , field = "properties.end_datetime" ),
343+ Q (
344+ "range" ,
345+ properties__start_datetime = {
346+ "lte" : datetime_search ["eq" ]
347+ },
348+ ),
349+ Q (
350+ "range" ,
351+ properties__end_datetime = {"gte" : datetime_search ["eq" ]},
352+ ),
353+ ],
354+ ),
355+ ]
356+ else :
357+ # For date ranges, include:
358+ # 1. Items with datetime in the range
359+ # 2. Items with datetime:null that overlap the search range
360+ should = [
361+ Q (
362+ "bool" ,
363+ filter = [
364+ Q ("exists" , field = "properties.datetime" ),
365+ Q (
366+ "range" ,
367+ properties__datetime = {
368+ "gte" : datetime_search ["gte" ],
369+ "lte" : datetime_search ["lte" ],
370+ },
371+ ),
372+ ],
373+ ),
374+ Q (
375+ "bool" ,
376+ filter = [
377+ Q (
378+ "bool" ,
379+ should = [
380+ Q (
381+ "bool" ,
382+ must_not = [
383+ Q ("exists" , field = "properties.datetime" )
384+ ],
385+ ),
386+ Q ("term" , ** {"properties__datetime" : None }),
387+ ],
388+ minimum_should_match = 1 ,
389+ ),
390+ Q ("exists" , field = "properties.start_datetime" ),
391+ Q ("exists" , field = "properties.end_datetime" ),
392+ Q (
393+ "range" ,
394+ properties__start_datetime = {
395+ "lte" : datetime_search ["lte" ]
396+ },
397+ ),
398+ Q (
399+ "range" ,
400+ properties__end_datetime = {
401+ "gte" : datetime_search ["gte" ]
402+ },
403+ ),
404+ ],
405+ ),
406+ ]
407+
408+ return (
409+ search .query (Q ("bool" , should = should , minimum_should_match = 1 )),
410+ datetime_search ,
411+ )
412+ else :
413+ if "eq" in datetime_search :
414+ filter_query = Q (
317415 "bool" ,
318- must_not = [Q ("exists" , field = "properties.datetime" )],
319416 filter = [
320417 Q ("exists" , field = "properties.start_datetime" ),
321418 Q ("exists" , field = "properties.end_datetime" ),
@@ -328,29 +425,10 @@ def apply_datetime_filter(
328425 properties__end_datetime = {"gte" : datetime_search ["eq" ]},
329426 ),
330427 ],
331- ),
332- ]
333- else :
334- # For date ranges, include:
335- # 1. Items with datetime in the range
336- # 2. Items with datetime:null that overlap the search range
337- should = [
338- Q (
339- "bool" ,
340- filter = [
341- Q ("exists" , field = "properties.datetime" ),
342- Q (
343- "range" ,
344- properties__datetime = {
345- "gte" : datetime_search ["gte" ],
346- "lte" : datetime_search ["lte" ],
347- },
348- ),
349- ],
350- ),
351- Q (
428+ )
429+ else :
430+ filter_query = Q (
352431 "bool" ,
353- must_not = [Q ("exists" , field = "properties.datetime" )],
354432 filter = [
355433 Q ("exists" , field = "properties.start_datetime" ),
356434 Q ("exists" , field = "properties.end_datetime" ),
@@ -363,13 +441,8 @@ def apply_datetime_filter(
363441 properties__end_datetime = {"gte" : datetime_search ["gte" ]},
364442 ),
365443 ],
366- ),
367- ]
368-
369- return (
370- search .query (Q ("bool" , should = should , minimum_should_match = 1 )),
371- datetime_search ,
372- )
444+ )
445+ return search .query (filter_query ), datetime_search
373446
374447 @staticmethod
375448 def apply_bbox_filter (search : Search , bbox : List ):
0 commit comments