X-Git-Url: https://git.openstreetmap.org./nominatim.git/blobdiff_plain/cbe22149df0b71620258e439669a8d96ae390717..a8aec65fb4278666fafb8b3b655093a3d1f0ae2a:/nominatim/api/search/db_searches.py diff --git a/nominatim/api/search/db_searches.py b/nominatim/api/search/db_searches.py index cc352134..5a13061e 100644 --- a/nominatim/api/search/db_searches.py +++ b/nominatim/api/search/db_searches.py @@ -5,7 +5,7 @@ # Copyright (C) 2023 by the Nominatim developer community. # For a full list of authors see the git log. """ -Implementation of the acutal database accesses for forward search. +Implementation of the actual database accesses for forward search. """ from typing import List, Tuple, AsyncIterator, Dict, Any, Callable, cast import abc @@ -245,6 +245,7 @@ async def _get_tiger(conn: SearchConnection, place_ids: List[int], class AbstractSearch(abc.ABC): """ Encapuslation of a single lookup in the database. """ + SEARCH_PRIO: int = 2 def __init__(self, penalty: float) -> None: self.penalty = penalty @@ -448,6 +449,8 @@ class PoiSearch(AbstractSearch): class CountrySearch(AbstractSearch): """ Search for a country name or country code. """ + SEARCH_PRIO = 0 + def __init__(self, sdata: SearchData) -> None: super().__init__(sdata.penalty) self.countries = sdata.countries @@ -481,7 +484,14 @@ class CountrySearch(AbstractSearch): result.bbox = Bbox.from_wkb(row.bbox) results.append(result) - return results or await self.lookup_in_country_table(conn, details) + if not results: + results = await self.lookup_in_country_table(conn, details) + + if results: + details.min_rank = min(5, details.max_rank) + details.max_rank = min(25, details.max_rank) + + return results async def lookup_in_country_table(self, conn: SearchConnection, @@ -592,10 +602,24 @@ class PostcodeSearch(AbstractSearch): results = nres.SearchResults() for row in await conn.execute(sql, _details_to_bind_params(details)): - result = nres.create_from_postcode_row(row, nres.SearchResult) + p = conn.t.placex + placex_sql = _select_placex(p).add_columns(p.c.importance)\ + .where(sa.text("""class = 'boundary' + AND type = 'postal_code' + AND osm_type = 'R'"""))\ + .where(p.c.country_code == row.country_code)\ + .where(p.c.postcode == row.postcode)\ + .limit(1) + for prow in await conn.execute(placex_sql, _details_to_bind_params(details)): + result = nres.create_from_placex_row(prow, nres.SearchResult) + break + else: + result = nres.create_from_postcode_row(row, nres.SearchResult) + assert result - result.accuracy = row.accuracy - results.append(result) + if result.place_id not in details.excluded: + result.accuracy = row.accuracy + results.append(result) return results @@ -604,6 +628,8 @@ class PostcodeSearch(AbstractSearch): class PlaceSearch(AbstractSearch): """ Generic search for an address or named place. """ + SEARCH_PRIO = 1 + def __init__(self, extra_penalty: float, sdata: SearchData, expected_count: int) -> None: super().__init__(sdata.penalty + extra_penalty) self.countries = sdata.countries @@ -663,7 +689,7 @@ class PlaceSearch(AbstractSearch): sql = sql.where(tsearch.c.centroid .intersects(VIEWBOX_PARAM, use_index=details.viewbox.area < 0.2)) - elif self.expected_count >= 10000: + elif not self.postcodes and not self.housenumbers and self.expected_count >= 10000: sql = sql.where(tsearch.c.centroid .intersects(VIEWBOX2_PARAM, use_index=details.viewbox.area < 0.5)) @@ -688,7 +714,7 @@ class PlaceSearch(AbstractSearch): or (details.viewbox is not None and details.viewbox.area < 0.5): sql = sql.order_by( penalty - sa.case((tsearch.c.importance > 0, tsearch.c.importance), - else_=0.75001-(sa.cast(tsearch.c.search_rank, sa.Float())/40))) + else_=0.40001-(sa.cast(tsearch.c.search_rank, sa.Float())/75))) sql = sql.add_columns(t.c.importance)