Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API for querying polygons based on a bounding box #10

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion server/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from typing import AsyncGenerator

from app.db import lifespan
from app.queries import waterbody_observations_query
from app.queries import waterbody_observations_query, bbox_query


app = FastAPI(lifespan=lifespan)
Expand Down Expand Up @@ -141,6 +141,54 @@ async def get_waterbody_geometry(wb_id: int, request: Request) -> Feature:
return waterbody_geom[0]


async def query_bbox(
request: Request,
minx: float,
miny: float,
maxx: float,
maxy: float
) -> AsyncGenerator[str, None]:
""" Async generator that yields a string (formatted as a CSV line) for each
row returned by the SQL query as the query is being run.
"""

# Before running the query, yield the csv header
yield "wb_id,geometry\n"

query = bbox_query(minx, miny, maxx, maxy)

async with request.app.async_pool.connection() as conn:
async with conn.cursor() as cursor:
async for bbox_geoms in cursor.stream(query):
# TODO - any changes to the query above need to be reflected here
wb_id, geometry = bbox_geoms
csv_line = f"{wb_id},{geometry}\n"
yield csv_line


@app.get("/waterbody/geometries/csv")
async def get_waterbody_geometries_csv(
request: Request,
minx: float = -14,
miny: float = 15,
maxx: float = -13,
maxy: float = 16
) -> StreamingResponse:
"""
Returns water body geometries in a CSV format
"""

async with request.app.async_pool.connection() as conn:
async with conn.cursor() as cur:
# Stream the reponse data, this means we don't need to keep a full copy
# of the water observations in memeory, and we can start writing the
# response as soon as the first row is read from the DB
return StreamingResponse(
query_bbox(request, minx, miny, maxx, maxy),
media_type='text/csv'
)


class CheckConnectionResult(BaseModel):
connected: bool

Expand Down
14 changes: 14 additions & 0 deletions server/app/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,18 @@ def waterbody_observations_query(wb_id: int, start_date: date, end_date: date) -
)
SELECT * from filtered_stats ORDER BY date
"""
return query

def bbox_query(minx: float, miny: float, maxx: float, maxy: float) -> str:

query = f"""
SELECT
wb_id,
ST_AsTWKB(geometry)
FROM
waterbodies_historical_extent
WHERE
geometry && ST_MakeEnvelope({minx}, {miny}, {maxx}, {maxy}, 4326)
"""

return query
Loading