python lookup: factor out finding in tables into own function

This commit is contained in:
Sarah Hoffmann 2023-04-03 10:00:42 +02:00
parent c92ac84679
commit 63638eb447
2 changed files with 41 additions and 26 deletions

View File

@ -20,7 +20,7 @@ from nominatim.db.sqlalchemy_schema import SearchTables
from nominatim.config import Configuration from nominatim.config import Configuration
from nominatim.api.connection import SearchConnection from nominatim.api.connection import SearchConnection
from nominatim.api.status import get_status, StatusResult from nominatim.api.status import get_status, StatusResult
from nominatim.api.lookup import get_place_by_id from nominatim.api.lookup import get_detailed_place
from nominatim.api.reverse import ReverseGeocoder from nominatim.api.reverse import ReverseGeocoder
from nominatim.api.types import PlaceRef, LookupDetails, AnyPoint, DataLayer from nominatim.api.types import PlaceRef, LookupDetails, AnyPoint, DataLayer
from nominatim.api.results import DetailedResult, ReverseResult from nominatim.api.results import DetailedResult, ReverseResult
@ -137,7 +137,7 @@ class NominatimAPIAsync:
Returns None if there is no entry under the given ID. Returns None if there is no entry under the given ID.
""" """
async with self.begin() as conn: async with self.begin() as conn:
return await get_place_by_id(conn, place, details or LookupDetails()) return await get_detailed_place(conn, place, details or LookupDetails())
async def reverse(self, coord: AnyPoint, max_rank: Optional[int] = None, async def reverse(self, coord: AnyPoint, max_rank: Optional[int] = None,

View File

@ -7,7 +7,7 @@
""" """
Implementation of place lookup by ID. Implementation of place lookup by ID.
""" """
from typing import Optional from typing import Optional, Callable, Tuple, Type
import datetime as dt import datetime as dt
import sqlalchemy as sa import sqlalchemy as sa
@ -18,6 +18,8 @@ import nominatim.api.types as ntyp
import nominatim.api.results as nres import nominatim.api.results as nres
from nominatim.api.logging import log from nominatim.api.logging import log
RowFunc = Callable[[Optional[SaRow], Type[nres.BaseResultT]], Optional[nres.BaseResultT]]
def _select_column_geometry(column: SaColumn, def _select_column_geometry(column: SaColumn,
geometry_output: ntyp.GeometryFormat) -> SaLabel: geometry_output: ntyp.GeometryFormat) -> SaLabel:
""" Create the appropriate column expression for selecting a """ Create the appropriate column expression for selecting a
@ -140,8 +142,34 @@ async def find_in_postcode(conn: SearchConnection, place: ntyp.PlaceRef,
return (await conn.execute(sql)).one_or_none() return (await conn.execute(sql)).one_or_none()
async def get_place_by_id(conn: SearchConnection, place: ntyp.PlaceRef, async def find_in_all_tables(conn: SearchConnection, place: ntyp.PlaceRef,
details: ntyp.LookupDetails) -> Optional[nres.DetailedResult]: details: ntyp.LookupDetails
) -> Tuple[Optional[SaRow], RowFunc[nres.BaseResultT]]:
""" Search for the given place in all data tables
and return the base information.
"""
row = await find_in_placex(conn, place, details)
log().var_dump('Result (placex)', row)
if row is not None:
return row, nres.create_from_placex_row
row = await find_in_osmline(conn, place, details)
log().var_dump('Result (osmline)', row)
if row is not None:
return row, nres.create_from_osmline_row
row = await find_in_postcode(conn, place, details)
log().var_dump('Result (postcode)', row)
if row is not None:
return row, nres.create_from_postcode_row
row = await find_in_tiger(conn, place, details)
log().var_dump('Result (tiger)', row)
return row, nres.create_from_tiger_row
async def get_detailed_place(conn: SearchConnection, place: ntyp.PlaceRef,
details: ntyp.LookupDetails) -> Optional[nres.DetailedResult]:
""" Retrieve a place with additional details from the database. """ Retrieve a place with additional details from the database.
""" """
log().function('get_place_by_id', place=place, details=details) log().function('get_place_by_id', place=place, details=details)
@ -149,27 +177,14 @@ async def get_place_by_id(conn: SearchConnection, place: ntyp.PlaceRef,
if details.geometry_output and details.geometry_output != ntyp.GeometryFormat.GEOJSON: if details.geometry_output and details.geometry_output != ntyp.GeometryFormat.GEOJSON:
raise ValueError("lookup only supports geojosn polygon output.") raise ValueError("lookup only supports geojosn polygon output.")
row = await find_in_placex(conn, place, details) row_func: RowFunc[nres.DetailedResult]
log().var_dump('Result (placex)', row) row, row_func = await find_in_all_tables(conn, place, details)
if row is not None:
result = nres.create_from_placex_row(row, nres.DetailedResult) if row is None:
else: return None
row = await find_in_osmline(conn, place, details)
log().var_dump('Result (osmline)', row) result = row_func(row, nres.DetailedResult)
if row is not None: assert result is not None
result = nres.create_from_osmline_row(row, nres.DetailedResult)
else:
row = await find_in_postcode(conn, place, details)
log().var_dump('Result (postcode)', row)
if row is not None:
result = nres.create_from_postcode_row(row, nres.DetailedResult)
else:
row = await find_in_tiger(conn, place, details)
log().var_dump('Result (tiger)', row)
if row is not None:
result = nres.create_from_tiger_row(row, nres.DetailedResult)
else:
return None
# add missing details # add missing details
assert result is not None assert result is not None