]> git.openstreetmap.org Git - nominatim.git/blobdiff - nominatim/api/search/db_searches.py
disallow category tokens in the middle of a query string
[nominatim.git] / nominatim / api / search / db_searches.py
index ee98100c637fbe3365b99c85951e07bf92c4055f..555819e7451dac76042482cd101ffbdfd067c882 100644 (file)
@@ -7,7 +7,7 @@
 """
 Implementation of the acutal database accesses for forward search.
 """
-from typing import List, Tuple, AsyncIterator, Dict, Any, Callable
+from typing import List, Tuple, AsyncIterator, Dict, Any, Callable, cast
 import abc
 
 import sqlalchemy as sa
@@ -190,7 +190,7 @@ def _int_list_to_subquery(inp: List[int]) -> 'sa.Subquery':
         as rows in the column 'nr'.
     """
     vtab = sa.func.JsonArrayEach(sa.type_coerce(inp, sa.JSON))\
-               .table_valued(sa.column('value', type_=sa.JSON)) # type: ignore[no-untyped-call]
+               .table_valued(sa.column('value', type_=sa.JSON))
     return sa.select(sa.cast(sa.cast(vtab.c.value, sa.Text), sa.Integer).label('nr')).subquery()
 
 
@@ -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,
@@ -604,6 +614,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
@@ -656,14 +668,14 @@ class PlaceSearch(AbstractSearch):
                       .where(tpc.c.postcode.in_(pcs))\
                       .scalar_subquery()
             penalty += sa.case((t.c.postcode.in_(pcs), 0.0),
-                               else_=sa.func.coalesce(pc_near, 2.0))
+                               else_=sa.func.coalesce(pc_near, cast(SaColumn, 2.0)))
 
         if details.viewbox is not None:
             if details.bounded_viewbox:
                 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))