@@ -1163,3 +1163,205 @@ async def test_search_datetime_with_null_datetime(
11631163 await txn_client .delete_collection (test_collection ["id" ])
11641164 except Exception as e :
11651165 logger .warning (f"Failed to delete collection: { e } " )
1166+
1167+
1168+ @pytest .mark .asyncio
1169+ async def test_search_cql2_json_datetime_operators (app_client , ctx ):
1170+ """Test POST search with CQL2-JSON datetime filter operators"""
1171+
1172+ test_item = ctx .item
1173+ item_datetime = test_item ["properties" ]["datetime" ]
1174+
1175+ cql2_equal = {
1176+ "filter-lang" : "cql2-json" ,
1177+ "filter" : {"op" : "=" , "args" : [{"property" : "datetime" }, item_datetime ]},
1178+ }
1179+ resp = await app_client .post ("/search" , json = cql2_equal )
1180+ assert resp .status_code == 200
1181+ resp_json = resp .json ()
1182+ assert resp_json ["features" ][0 ]["id" ] == test_item ["id" ]
1183+
1184+ later_datetime = "2020-02-13T12:30:22Z"
1185+ cql2_lte = {
1186+ "filter-lang" : "cql2-json" ,
1187+ "filter" : {"op" : "<=" , "args" : [{"property" : "datetime" }, later_datetime ]},
1188+ }
1189+ resp = await app_client .post ("/search" , json = cql2_lte )
1190+ assert resp .status_code == 200
1191+ resp_json = resp .json ()
1192+ assert resp_json ["features" ][0 ]["id" ] == test_item ["id" ]
1193+
1194+ earlier_datetime = "2020-02-11T12:30:22Z"
1195+ cql2_gte = {
1196+ "filter-lang" : "cql2-json" ,
1197+ "filter" : {"op" : ">=" , "args" : [{"property" : "datetime" }, earlier_datetime ]},
1198+ }
1199+ resp = await app_client .post ("/search" , json = cql2_gte )
1200+ assert resp .status_code == 200
1201+ resp_json = resp .json ()
1202+ assert resp_json ["features" ][0 ]["id" ] == test_item ["id" ]
1203+
1204+ range_start = "2020-02-12T00:00:00Z"
1205+ range_end = "2020-02-13T00:00:00Z"
1206+ cql2_between = {
1207+ "filter-lang" : "cql2-json" ,
1208+ "filter" : {
1209+ "op" : "and" ,
1210+ "args" : [
1211+ {"op" : ">=" , "args" : [{"property" : "datetime" }, range_start ]},
1212+ {"op" : "<=" , "args" : [{"property" : "datetime" }, range_end ]},
1213+ ],
1214+ },
1215+ }
1216+ resp = await app_client .post ("/search" , json = cql2_between )
1217+ assert resp .status_code == 200
1218+ resp_json = resp .json ()
1219+ assert resp_json ["features" ][0 ]["id" ] == test_item ["id" ]
1220+
1221+
1222+ @pytest .mark .asyncio
1223+ async def test_search_cql2_json_start_end_datetime_operators (app_client , ctx ):
1224+ """Test POST search with CQL2-JSON start_datetime and end_datetime filter operators"""
1225+
1226+ test_item = ctx .item
1227+ start_datetime = test_item ["properties" ]["start_datetime" ] # "2020-02-08T12:30:22Z"
1228+ end_datetime = test_item ["properties" ]["end_datetime" ] # "2020-02-16T12:30:22Z"
1229+
1230+ cql2_start_equal = {
1231+ "filter-lang" : "cql2-json" ,
1232+ "filter" : {"op" : "=" , "args" : [{"property" : "start_datetime" }, start_datetime ]},
1233+ }
1234+ resp = await app_client .post ("/search" , json = cql2_start_equal )
1235+ assert resp .status_code == 200
1236+ resp_json = resp .json ()
1237+ assert resp_json ["features" ][0 ]["id" ] == test_item ["id" ]
1238+
1239+ later_start = "2020-02-09T12:30:22Z"
1240+ cql2_start_lte = {
1241+ "filter-lang" : "cql2-json" ,
1242+ "filter" : {"op" : "<=" , "args" : [{"property" : "start_datetime" }, later_start ]},
1243+ }
1244+ resp = await app_client .post ("/search" , json = cql2_start_lte )
1245+ assert resp .status_code == 200
1246+ resp_json = resp .json ()
1247+ assert resp_json ["features" ][0 ]["id" ] == test_item ["id" ]
1248+
1249+ earlier_start = "2020-02-07T12:30:22Z"
1250+ cql2_start_gte = {
1251+ "filter-lang" : "cql2-json" ,
1252+ "filter" : {"op" : ">=" , "args" : [{"property" : "start_datetime" }, earlier_start ]},
1253+ }
1254+ resp = await app_client .post ("/search" , json = cql2_start_gte )
1255+ assert resp .status_code == 200
1256+ resp_json = resp .json ()
1257+ assert resp_json ["features" ][0 ]["id" ] == test_item ["id" ]
1258+
1259+ start_range_start = "2020-02-08T00:00:00Z"
1260+ start_range_end = "2020-02-09T00:00:00Z"
1261+ cql2_start_between = {
1262+ "filter-lang" : "cql2-json" ,
1263+ "filter" : {
1264+ "op" : "and" ,
1265+ "args" : [
1266+ {
1267+ "op" : ">=" ,
1268+ "args" : [{"property" : "start_datetime" }, start_range_start ],
1269+ },
1270+ {"op" : "<=" , "args" : [{"property" : "start_datetime" }, start_range_end ]},
1271+ ],
1272+ },
1273+ }
1274+ resp = await app_client .post ("/search" , json = cql2_start_between )
1275+ assert resp .status_code == 200
1276+ resp_json = resp .json ()
1277+ assert resp_json ["features" ][0 ]["id" ] == test_item ["id" ]
1278+
1279+ cql2_end_equal = {
1280+ "filter-lang" : "cql2-json" ,
1281+ "filter" : {"op" : "=" , "args" : [{"property" : "end_datetime" }, end_datetime ]},
1282+ }
1283+ resp = await app_client .post ("/search" , json = cql2_end_equal )
1284+ assert resp .status_code == 200
1285+ resp_json = resp .json ()
1286+ assert resp_json ["features" ][0 ]["id" ] == test_item ["id" ]
1287+
1288+ later_end = "2020-02-17T12:30:22Z"
1289+ cql2_end_lte = {
1290+ "filter-lang" : "cql2-json" ,
1291+ "filter" : {"op" : "<=" , "args" : [{"property" : "end_datetime" }, later_end ]},
1292+ }
1293+ resp = await app_client .post ("/search" , json = cql2_end_lte )
1294+ assert resp .status_code == 200
1295+ resp_json = resp .json ()
1296+ assert resp_json ["features" ][0 ]["id" ] == test_item ["id" ]
1297+
1298+ earlier_end = "2020-02-15T12:30:22Z"
1299+ cql2_end_gte = {
1300+ "filter-lang" : "cql2-json" ,
1301+ "filter" : {"op" : ">=" , "args" : [{"property" : "end_datetime" }, earlier_end ]},
1302+ }
1303+ resp = await app_client .post ("/search" , json = cql2_end_gte )
1304+ assert resp .status_code == 200
1305+ resp_json = resp .json ()
1306+ assert resp_json ["features" ][0 ]["id" ] == test_item ["id" ]
1307+
1308+ end_range_start = "2020-02-16T00:00:00Z"
1309+ end_range_end = "2020-02-17T00:00:00Z"
1310+ cql2_end_between = {
1311+ "filter-lang" : "cql2-json" ,
1312+ "filter" : {
1313+ "op" : "and" ,
1314+ "args" : [
1315+ {"op" : ">=" , "args" : [{"property" : "end_datetime" }, end_range_start ]},
1316+ {"op" : "<=" , "args" : [{"property" : "end_datetime" }, end_range_end ]},
1317+ ],
1318+ },
1319+ }
1320+ resp = await app_client .post ("/search" , json = cql2_end_between )
1321+ assert resp .status_code == 200
1322+ resp_json = resp .json ()
1323+ assert resp_json ["features" ][0 ]["id" ] == test_item ["id" ]
1324+
1325+ cql2_start_end_range = {
1326+ "filter-lang" : "cql2-json" ,
1327+ "filter" : {
1328+ "op" : "and" ,
1329+ "args" : [
1330+ {
1331+ "op" : ">=" ,
1332+ "args" : [{"property" : "start_datetime" }, "2020-02-07T12:30:22Z" ],
1333+ },
1334+ {
1335+ "op" : "<=" ,
1336+ "args" : [{"property" : "end_datetime" }, "2020-02-17T12:30:22Z" ],
1337+ },
1338+ ],
1339+ },
1340+ }
1341+ resp = await app_client .post ("/search" , json = cql2_start_end_range )
1342+ assert resp .status_code == 200
1343+ resp_json = resp .json ()
1344+ assert resp_json ["features" ][0 ]["id" ] == test_item ["id" ]
1345+
1346+
1347+ @pytest .mark .asyncio
1348+ async def test_select_indexes (txn_client , load_test_data ):
1349+ """Run select_indexes test."""
1350+
1351+ database = txn_client .database
1352+ index_selector = database .async_index_selector
1353+
1354+ collection = load_test_data ("test_collection.json" )
1355+ collection_id = "test-collection-1"
1356+ collection ["id" ] = collection_id
1357+
1358+ test_item = load_test_data ("test_item.json" )
1359+ test_item ["id" ] = "test-item-1"
1360+
1361+ result = await index_selector .select_indexes (
1362+ ["test-collection-1" ],
1363+ {"gte" : "2024-01-01T00:00:00Z" , "lte" : "2024-12-31T23:59:59Z" },
1364+ )
1365+
1366+ assert result is not None
1367+ assert result == "items_test-collection-1"
0 commit comments