]> git.openstreetmap.org Git - nominatim.git/blobdiff - nominatim/api/results.py
don't even try heavily penalized searches
[nominatim.git] / nominatim / api / results.py
index 829008fb3ec316a09a753b39cb720404b1c8d98b..47fb85114634de804f36fa569dc79986894dccc4 100644 (file)
@@ -11,7 +11,7 @@ Data classes are part of the public API while the functions are for
 internal use only. That's why they are implemented as free-standing functions
 instead of member functions.
 """
-from typing import Optional, Tuple, Dict, Sequence, TypeVar, Type, List, cast
+from typing import Optional, Tuple, Dict, Sequence, TypeVar, Type, List, cast, Callable
 import enum
 import dataclasses
 import datetime as dt
@@ -233,7 +233,7 @@ class BaseResult:
             of the value or an artificial value computed from the place's
             search rank.
         """
-        return self.importance or (0.7500001 - (self.rank_search/40.0))
+        return self.importance or (0.40001 - (self.rank_search/75.0))
 
 
     def localize(self, locales: Locales) -> None:
@@ -466,7 +466,7 @@ async def add_result_details(conn: SearchConnection, results: List[BaseResultT],
 
 
 def _result_row_to_address_row(row: SaRow, isaddress: Optional[bool] = None) -> AddressLine:
-    """ Create a new AddressLine from the results of a datbase query.
+    """ Create a new AddressLine from the results of a database query.
     """
     extratags: Dict[str, str] = getattr(row, 'extratags', {}) or {}
     if 'linked_place' in extratags:
@@ -501,15 +501,17 @@ def _get_address_lookup_id(result: BaseResultT) -> int:
 
 async def _finalize_entry(conn: SearchConnection, result: BaseResultT) -> None:
     assert result.address_rows is not None
-    postcode = result.postcode
-    if not postcode and result.address:
-        postcode = result.address.get('postcode')
-    if postcode and ',' not in postcode and ';' not in postcode:
-        result.address_rows.append(AddressLine(
-            category=('place', 'postcode'),
-            names={'ref': postcode},
-            fromarea=False, isaddress=True, rank_address=5,
-            distance=0.0))
+    if result.category[0] not in ('boundary', 'place')\
+       or result.category[1] not in ('postal_code', 'postcode'):
+        postcode = result.postcode
+        if not postcode and result.address:
+            postcode = result.address.get('postcode')
+        if postcode and ',' not in postcode and ';' not in postcode:
+            result.address_rows.append(AddressLine(
+                category=('place', 'postcode'),
+                names={'ref': postcode},
+                fromarea=False, isaddress=True, rank_address=5,
+                distance=0.0))
     if result.country_code:
         async def _get_country_names() -> Optional[Dict[str, str]]:
             t = conn.t.country_name
@@ -551,7 +553,7 @@ def _setup_address_details(result: BaseResultT) -> None:
             extratags=result.extratags or {},
             admin_level=result.admin_level,
             fromarea=True, isaddress=True,
-            rank_address=result.rank_address or 100, distance=0.0))
+            rank_address=result.rank_address, distance=0.0))
     if result.source_table == SourceTable.PLACEX and result.address:
         housenumber = result.address.get('housenumber')\
                       or result.address.get('streetnumber')\
@@ -590,7 +592,7 @@ async def complete_address_details(conn: SearchConnection, results: List[BaseRes
         return
 
     ltab = sa.func.JsonArrayEach(sa.type_coerce(lookup_ids, sa.JSON))\
-             .table_valued(sa.column('value', type_=sa.JSON)) # type: ignore[no-untyped-call]
+             .table_valued(sa.column('value', type_=sa.JSON))
 
     t = conn.t.placex
     taddr = conn.t.addressline
@@ -653,7 +655,7 @@ async def complete_address_details(conn: SearchConnection, results: List[BaseRes
     parent_lookup_ids = list(filter(lambda e: e['pid'] != e['lid'], lookup_ids))
     if parent_lookup_ids:
         ltab = sa.func.JsonArrayEach(sa.type_coerce(parent_lookup_ids, sa.JSON))\
-                 .table_valued(sa.column('value', type_=sa.JSON)) # type: ignore[no-untyped-call]
+                 .table_valued(sa.column('value', type_=sa.JSON))
         sql = sa.select(ltab.c.value['pid'].as_integer().label('src_place_id'),
                         t.c.place_id, t.c.osm_type, t.c.osm_id, t.c.name,
                         t.c.class_, t.c.type, t.c.extratags,
@@ -676,9 +678,12 @@ async def complete_address_details(conn: SearchConnection, results: List[BaseRes
                     rank_address=row.rank_address, distance=0.0))
 
     ### Now sort everything
+    def mk_sort_key(place_id: Optional[int]) -> Callable[[AddressLine], Tuple[bool, int, bool]]:
+        return lambda a: (a.place_id != place_id, -a.rank_address, a.isaddress)
+
     for result in results:
         assert result.address_rows is not None
-        result.address_rows.sort(key=lambda a: (-a.rank_address, a.isaddress))
+        result.address_rows.sort(key=mk_sort_key(result.place_id))
 
 
 def _placex_select_address_row(conn: SearchConnection,