Skip to content

Commit

Permalink
fix filter extension implementation (#149)
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentsarago authored Sep 25, 2024
1 parent c7b17e6 commit c89360c
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

- Fix Docker compose file, so example data can be loaded into database (author @zstatmanweil, https://github.com/stac-utils/stac-fastapi-pgstac/pull/142)

- Fix `filter` extension implementation in `CoreCrudClient`

## [3.0.0] - 2024-08-02

- Enable filter extension for `GET /items` requests and add `Queryables` links in `/collections` and `/collections/{collection_id}` responses ([#89](https://github.com/stac-utils/stac-fastapi-pgstac/pull/89))
Expand Down
5 changes: 2 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: '3'
services:
app:
container_name: stac-fastapi-pgstac
Expand Down Expand Up @@ -67,8 +66,8 @@ services:
- ./scripts:/app/scripts
command: >
/bin/sh -c "
./scripts/wait-for-it.sh -t 60 app:8082 &&
python -m pip install requests &&
./scripts/wait-for-it.sh -t 60 app:8082 &&
python -m pip install requests &&
python /app/scripts/ingest_joplin.py http://app:8082
"
depends_on:
Expand Down
21 changes: 13 additions & 8 deletions stac_fastapi/pgstac/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,11 +310,14 @@ async def item_collection(

if self.extension_is_enabled("FilterExtension"):
filter_lang = kwargs.get("filter_lang", None)
filter = kwargs.get("filter", None)
if filter is not None and filter_lang == "cql2-text":
ast = parse_cql2_text(filter.strip())
base_args["filter"] = orjson.loads(to_cql2(ast))
base_args["filter-lang"] = "cql2-json"
filter_query = kwargs.get("filter", None)
if filter_query:
if filter_lang == "cql2-text":
filter_query = to_cql2(parse_cql2_text(filter_query))
filter_lang = "cql2-json"

base_args["filter"] = orjson.loads(filter_query)
base_args["filter-lang"] = filter_lang

clean = {}
for k, v in base_args.items():
Expand Down Expand Up @@ -420,9 +423,11 @@ async def get_search( # noqa: C901

if filter:
if filter_lang == "cql2-text":
ast = parse_cql2_text(filter)
base_args["filter"] = orjson.loads(to_cql2(ast))
base_args["filter-lang"] = "cql2-json"
filter = to_cql2(parse_cql2_text(filter))
filter_lang = "cql2-json"

base_args["filter"] = orjson.loads(filter)
base_args["filter-lang"] = filter_lang

if datetime:
base_args["datetime"] = format_datetime_range(datetime)
Expand Down
113 changes: 113 additions & 0 deletions tests/resources/test_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -1540,3 +1540,116 @@ async def test_get_collection_items_duplicate_forwarded_headers(
)
for link in resp.json()["features"][0]["links"]:
assert link["href"].startswith("https://test:1234/")


async def test_get_filter_extension(app_client, load_test_data, load_test_collection):
"""Test GET with Filter extension"""
test_item = load_test_data("test_item.json")
collection_id = test_item["collection"]
ids = []

# Ingest 5 items
for _ in range(5):
uid = str(uuid.uuid4())
test_item["id"] = uid
resp = await app_client.post(
f"/collections/{collection_id}/items", json=test_item
)
assert resp.status_code == 201
ids.append(uid)

search_id = ids[2]

# SEARCH
# CQL2-JSON
resp = await app_client.get(
"/search",
params={
"filter-lang": "cql2-json",
"filter": json.dumps({"op": "in", "args": [{"property": "id"}, [search_id]]}),
},
)
assert resp.status_code == 200
fc = resp.json()
assert len(fc["features"]) == 1
assert fc["features"][0]["id"] == search_id

# CQL-JSON
resp = await app_client.get(
"/search",
params={
"filter-lang": "cql-json",
"filter": json.dumps(
{
"eq": [
{"property": "id"},
search_id,
],
},
),
},
)
assert resp.status_code == 200
fc = resp.json()
assert len(fc["features"]) == 1
assert fc["features"][0]["id"] == search_id

# CQL2-TEXT
resp = await app_client.get(
"/search",
params={
"filter-lang": "cql2-text",
"filter": f"id='{search_id}'",
},
)
assert resp.status_code == 200
fc = resp.json()
assert len(fc["features"]) == 1
assert fc["features"][0]["id"] == search_id

# ITEM COLLECTION
# CQL2-JSON
resp = await app_client.get(
f"/collections/{collection_id}/items",
params={
"filter-lang": "cql2-json",
"filter": json.dumps({"op": "in", "args": [{"property": "id"}, [search_id]]}),
},
)
assert resp.status_code == 200
fc = resp.json()
assert len(fc["features"]) == 1
assert fc["features"][0]["id"] == search_id

# CQL-JSON
resp = await app_client.get(
f"/collections/{collection_id}/items",
params={
"filter-lang": "cql-json",
"filter": json.dumps(
{
"eq": [
{"property": "id"},
search_id,
],
},
),
},
)
assert resp.status_code == 200
fc = resp.json()
assert len(fc["features"]) == 1
assert fc["features"][0]["id"] == search_id

# CQL2-TEXT
resp = await app_client.get(
f"/collections/{collection_id}/items",
params={
"filter-lang": "cql2-text",
"filter": f"id='{search_id}'",
},
)
assert resp.status_code == 200
fc = resp.json()
assert len(fc["features"]) == 1
assert fc["features"][0]["id"] == search_id

0 comments on commit c89360c

Please sign in to comment.