]> git.openstreetmap.org Git - nominatim.git/commitdiff
Search housenumbers with unknown address parts by housenumber term
authorSarah Hoffmann <lonvia@denofr.de>
Thu, 19 Nov 2020 11:06:53 +0000 (12:06 +0100)
committerSarah Hoffmann <lonvia@denofr.de>
Wed, 25 Nov 2020 10:36:10 +0000 (11:36 +0100)
House numbers need special handling because they may appear after
the street term. That means we canot just use them as the main name
for searches where the address has its own search term entries.
Doing this right now, we are able to find '40, Main St, Town' but not
'Main St 40, Town'.

This switches to using the housenumber token as the name term instead.
House number tokens can get special handling when building the search
query that covers the case where they come after the street.

The main disadvantage is that this once more increases the numbers
of possible search interpretation of which we have already too many.

no penalty for housenumber searches

lib/SearchDescription.php
sql/functions/normalization.sql
test/bdd/db/import/search_name.feature
test/bdd/steps/db_ops.py
utils/query.php

index ad404528968ad94075bc414af0bc0f5a185873cc..c339b108e749953636736bff2a7e1e2aacfe4ae5 100644 (file)
@@ -247,6 +247,15 @@ class SearchDescription
                     $oSearch->iSearchRank++;
                 }
                 $aNewSearches[] = $oSearch;
+                // Housenumbers may appear in the name when the place has its own
+                // address terms.
+                if (($this->iNamePhrase >= 0 || empty($this->aName)) && empty($this->aAddress)) {
+                    $oSearch = clone $this;
+                    $oSearch->iSearchRank++;
+                    $oSearch->aAddress = $this->aName;
+                    $oSearch->aName = array($oSearchTerm->iId => $oSearchTerm->iId);
+                    $aNewSearches[] = $oSearch;
+                }
             }
         } elseif ($sPhraseType == ''
                   && is_a($oSearchTerm, '\Nominatim\Token\SpecialTerm')
index 4aea0e9ba3673854dd4cf8ed7dea492916600b66..8bb4915bbf8612ab858c98345409bbef57ff6eb0 100644 (file)
@@ -490,53 +490,34 @@ BEGIN
     END LOOP;
   END IF;
 
-
-  -- If the POI is named, simply mix in all address terms and be done.
-  IF array_length(initial_name_vector, 1) is not NULL THEN
-    -- Cheating here by not recomputing all terms but simply using the ones
-    -- from the parent object.
-    name_vector := initial_name_vector;
-    nameaddress_vector := array_merge(nameaddress_vector, parent_name_vector);
-    nameaddress_vector := array_merge(nameaddress_vector, parent_address_vector);
-
-    IF not address ? 'street' and address ? 'place' THEN
-      -- make sure addr:place terms are always searchable
-      nameaddress_vector := array_merge(nameaddress_vector,
-                                        addr_ids_from_name(address->'place'));
-    END IF;
-
-    RETURN;
-  END IF;
-
-  ----- unnamed POIS
-
-  IF (array_length(nameaddress_vector, 1) is null
-      and (address ? 'street'or not address ? 'place'))
-     or housenumber is null
-  THEN
-    RETURN;
-  END IF;
+  name_vector := initial_name_vector;
 
   -- Check if the parent covers all address terms.
   -- If not, create a search name entry with the house number as the name.
   -- This is unusual for the search_name table but prevents that the place
   -- is returned when we only search for the street/place.
 
-  IF not nameaddress_vector <@ parent_address_vector THEN
-    name_vector := ARRAY[getorcreate_name_id(housenumber)];
+  IF housenumber is not null and not nameaddress_vector <@ parent_address_vector THEN
+    name_vector := array_merge(name_vector,
+                               ARRAY[getorcreate_housenumber_id(make_standard_name(housenumber))]);
   END IF;
 
   IF not address ? 'street' and address ? 'place' THEN
     addr_place_ids := addr_ids_from_name(address->'place');
     IF not addr_place_ids <@ parent_name_vector THEN
-      -- addr:place tag exists without a corresponding place. Mix in addr:place
-      -- in the address.
-      name_vector := ARRAY[getorcreate_name_id(housenumber)];
+      -- make sure addr:place terms are always searchable
       nameaddress_vector := array_merge(nameaddress_vector, addr_place_ids);
+      -- If there is a housenumber, also add the place name as a name,
+      -- so we can search it by the usual housenumber+place algorithms.
+      IF housenumber is not null THEN
+        name_vector := array_merge(name_vector,
+                                   ARRAY[getorcreate_name_id(make_standard_name(address->'place'))]);
+      END IF;
     END IF;
   END IF;
 
-  -- Merge the parent name and address.
+  -- Cheating here by not recomputing all terms but simply using the ones
+  -- from the parent object.
   nameaddress_vector := array_merge(nameaddress_vector, parent_name_vector);
   nameaddress_vector := array_merge(nameaddress_vector, parent_address_vector);
 
index 30c430a6b4503e33da91aa4d53a04eb8e9db4d25..0e922e1d6b503716f649ff8b13409adf21bd9a1f 100644 (file)
@@ -23,12 +23,20 @@ Feature: Creation of search terms
          | W1  | highway | residential | Rose Street | :w-north |
         When importing
         Then search_name contains
-         | object | name_vector | nameaddress_vector |
-         | N1     | #23         | Rose Street, Walltown |
+         | object | nameaddress_vector |
+         | N1     | Rose, Street, Walltown |
         When searching for "23 Rose Street, Walltown"
         Then results contain
          | osm_type | osm_id | name |
          | N        | 1      | 23, Rose Street |
+        When searching for "Walltown, Rose Street 23"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | 23, Rose Street |
+        When searching for "Rose Street 23, Walltown"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | 23, Rose Street |
 
     Scenario: Searching for unknown addr: tags also works for multiple words
         Given the scene roads-with-pois
@@ -40,12 +48,20 @@ Feature: Creation of search terms
          | W1  | highway | residential | Rose Street | :w-north |
         When importing
         Then search_name contains
-         | object | name_vector | nameaddress_vector |
-         | N1     | #23         | Rose Street, Little, Big, Town |
+         | object | nameaddress_vector |
+         | N1     | Rose Street, Little, Big, Town |
         When searching for "23 Rose Street, Little Big Town"
         Then results contain
          | osm_type | osm_id | name |
          | N        | 1      | 23, Rose Street |
+        When searching for "Rose Street 23, Little Big Town"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | 23, Rose Street |
+        When searching for "Little big Town, Rose Street 23"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | 23, Rose Street |
 
      Scenario: Unnamed POI has no search entry when it has known addr: tags
         Given the scene roads-with-pois
@@ -88,7 +104,7 @@ Feature: Creation of search terms
          | N1     | N2              |
         Then search_name contains
          | object | name_vector | nameaddress_vector |
-         | N1     | #23         | Walltown, Strange, Town |
+         | N1     | #Walltown   | Strange, Town |
         When searching for "23 Rose Street"
         Then exactly 1 results are returned
         And results contain
@@ -98,6 +114,70 @@ Feature: Creation of search terms
         Then results contain
          | osm_type | osm_id | name |
          | N        | 1      | 23, Walltown, Strange Town |
+        When searching for "Walltown 23, Strange Town"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | 23, Walltown, Strange Town |
+        When searching for "Strange Town, Walltown 23"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | 23, Walltown, Strange Town |
+
+    Scenario: Named POIs can be searched by housenumber when unknown addr:place is present
+        Given the scene roads-with-pois
+        And the places
+         | osm | class   | type  | name       | housenr | addr+place | geometry |
+         | N1  | place   | house | Blue house | 23      | Walltown   | :p-N1 |
+        And the places
+         | osm | class   | type        | name+name    | geometry |
+         | W1  | highway | residential | Rose Street  | :w-north |
+         | N2  | place   | city        | Strange Town | :p-N1 |
+        When importing
+        Then search_name contains
+         | object | name_vector      | nameaddress_vector      |
+         | N1     | #Walltown, #Blue house | Walltown, Strange, Town |
+        When searching for "23 Walltown, Strange Town"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | Blue house, 23, Walltown, Strange Town |
+        When searching for "Walltown 23, Strange Town"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | Blue house, 23, Walltown, Strange Town |
+        When searching for "Strange Town, Walltown 23"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | Blue house, 23, Walltown, Strange Town |
+        When searching for "Strange Town, Walltown 23, Blue house"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | Blue house, 23, Walltown, Strange Town |
+        When searching for "Strange Town, Walltown, Blue house"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | Blue house, 23, Walltown, Strange Town |
+
+    Scenario: Named POIs can be found when unknown multi-word addr:place is present
+        Given the scene roads-with-pois
+        And the places
+         | osm | class   | type  | name       | housenr | addr+place | geometry |
+         | N1  | place   | house | Blue house | 23      | Moon sun   | :p-N1 |
+        And the places
+         | osm | class   | type        | name+name    | geometry |
+         | W1  | highway | residential | Rose Street  | :w-north |
+         | N2  | place   | city        | Strange Town | :p-N1 |
+        When importing
+        Then search_name contains
+         | object | name_vector      | nameaddress_vector      |
+         | N1     | #Moon sun, #Blue house | Moon, Sun, Strange, Town |
+        When searching for "23 Moon Sun, Strange Town"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | Blue house, 23, Moon sun, Strange Town |
+        When searching for "Blue house, Moon Sun, Strange Town"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | Blue house, 23, Moon sun, Strange Town |
 
     Scenario: Unnamed POIs doesn't inherit parent name when addr:place is present only in parent address
         Given the scene roads-with-pois
@@ -111,7 +191,7 @@ Feature: Creation of search terms
         When importing
         Then search_name contains
          | object | name_vector | nameaddress_vector |
-         | N1     | #23         | Walltown |
+         | N1     | #Walltown   | Strange, Town      |
         When searching for "23 Rose Street, Walltown"
         Then exactly 1 result is returned
         And results contain
@@ -157,22 +237,38 @@ Feature: Creation of search terms
         When searching for "23 Lily Street"
         Then exactly 0 results are returned
 
-    Scenario: Named POIs have unknown address tags added in the search_name table
+    Scenario: Named POIs get unknown address tags added in the search_name table
         Given the scene roads-with-pois
         And the places
-         | osm | class   | type        | name+name  | addr+city | geometry |
-         | N1  | place   | house       | Green Moss | Walltown  | :p-N1 |
+         | osm | class   | type        | name+name  | housenr | addr+city | geometry |
+         | N1  | place   | house       | Green Moss | 26      | Walltown  | :p-N1 |
         And the places
          | osm | class   | type        | name+name   | geometry |
          | W1  | highway | residential | Rose Street | :w-north |
         When importing
         Then search_name contains
          | object | name_vector | nameaddress_vector |
-         | N1     | #Green Moss | Rose Street, Walltown |
+         | N1     | #Green Moss | Rose, Street, Walltown |
         When searching for "Green Moss, Rose Street, Walltown"
         Then results contain
          | osm_type | osm_id | name |
-         | N        | 1      | Green Moss, Rose Street |
+         | N        | 1      | Green Moss, 26, Rose Street |
+        When searching for "Green Moss, 26, Rose Street, Walltown"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | Green Moss, 26, Rose Street |
+        When searching for "26, Rose Street, Walltown"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | Green Moss, 26, Rose Street |
+        When searching for "Rose Street 26, Walltown"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | Green Moss, 26, Rose Street |
+        When searching for "Walltown, Rose Street 26"
+        Then results contain
+         | osm_type | osm_id | name |
+         | N        | 1      | Green Moss, 26, Rose Street |
 
     Scenario: Named POI doesn't inherit parent name when addr:place is present only in parent address
         Given the scene roads-with-pois
index 377c977d412986de192537928117ff39b86188b0..2b012c41d9be286717b385310780083001cc1602 100644 (file)
@@ -487,8 +487,8 @@ def check_search_name_contents(context, exclude):
                                    """,
                                    (terms, words))
                     if not exclude:
-                        ok_(subcur.rowcount >= len(terms),
-                            "No word entry found for " + row[h])
+                        ok_(subcur.rowcount >= len(terms) + len(words),
+                            "No word entry found for " + row[h] + ". Entries found: " + str(subcur.rowcount))
                     for wid in subcur:
                         if exclude:
                             assert_not_in(wid[0], res[h],
index 956bb56634bddd79ad295d1b7cd9d75a4fd552f3..6068c7c00af9efbd18f68db0fd021a17808472b9 100644 (file)
@@ -58,6 +58,7 @@ if (!$oParams->hasSetAny($aSearchParams)) {
 $oGeocode = new Nominatim\Geocode($oDB);
 
 $oGeocode->setLanguagePreference($oParams->getPreferredLanguages(false));
+$oGeocode->setReverseInPlan(true);
 $oGeocode->loadParamArray($oParams);
 
 if ($oParams->getBool('search')) {