From: Sarah Hoffmann Date: Thu, 17 Jun 2021 10:05:33 +0000 (+0200) Subject: do not return POIs when dropping house number in query X-Git-Tag: v4.0.0~63^2 X-Git-Url: https://git.openstreetmap.org./nominatim.git/commitdiff_plain/fe11d3cbbd22e73042ac657e76bb8aca447c8b50 do not return POIs when dropping house number in query We've previously added searching through rank 30 in a house number search to enable searches for house number+name. This had the unintended side effect that rank 30 objects are also returned in s search that dropped the house number from the query. This is wrong because POIs cannot function as a parent to a house number. This fix drops all rank 30 objects from the results for a house number search if they do not match the requested house number. --- diff --git a/lib-php/Result.php b/lib-php/Result.php index be103074..774b7ca6 100644 --- a/lib-php/Result.php +++ b/lib-php/Result.php @@ -55,6 +55,27 @@ class Result } ))); } + + public static function joinIdsByTableMinRank($aResults, $iTable, $iMinAddressRank) + { + return join(',', array_keys(array_filter( + $aResults, + function ($aValue) use ($iTable, $iMinAddressRank) { + return $aValue->iTable == $iTable && $aValue->iAddressRank >= $iMinAddressRank; + } + ))); + } + + public static function joinIdsByTableMaxRank($aResults, $iTable, $iMaxAddressRank) + { + return join(',', array_keys(array_filter( + $aResults, + function ($aValue) use ($iTable, $iMaxAddressRank) { + return $aValue->iTable == $iTable && $aValue->iAddressRank <= $iMaxAddressRank; + } + ))); + } + public static function sqlHouseNumberTable($aResults, $iTable) { $sHousenumbers = ''; diff --git a/lib-php/SearchDescription.php b/lib-php/SearchDescription.php index 8da49a9f..67cfbad0 100644 --- a/lib-php/SearchDescription.php +++ b/lib-php/SearchDescription.php @@ -447,23 +447,24 @@ class SearchDescription // Now search for housenumber, if housenumber provided. Can be zero. if (($this->sHouseNumber || $this->sHouseNumber === '0') && !empty($aResults)) { + $aHnResults = $this->queryHouseNumber($oDB, $aResults); + // Downgrade the rank of the street results, they are missing - // the housenumber. + // the housenumber. Also drop POI places (rank 30) here, they + // cannot be a parent place and therefore must not be shown + // as a result for a search with a missing housenumber. foreach ($aResults as $oRes) { - if ($oRes->iAddressRank >= 26) { - $oRes->iResultRank++; - } else { - $oRes->iResultRank += 2; + if ($oRes->iAddressRank < 28) { + if ($oRes->iAddressRank >= 26) { + $oRes->iResultRank++; + } else { + $oRes->iResultRank += 2; + } + $aHnResults[$oRes->iId] = $oRes; } } - $aHnResults = $this->queryHouseNumber($oDB, $aResults); - - if (!empty($aHnResults)) { - foreach ($aHnResults as $oRes) { - $aResults[$oRes->iId] = $oRes; - } - } + $aResults = $aHnResults; } // finally get POIs if requested @@ -743,16 +744,33 @@ class SearchDescription private function queryHouseNumber(&$oDB, $aRoadPlaceIDs) { $aResults = array(); - $sPlaceIDs = Result::joinIdsByTable($aRoadPlaceIDs, Result::TABLE_PLACEX); + $sRoadPlaceIDs = Result::joinIdsByTableMaxRank( + $aRoadPlaceIDs, + Result::TABLE_PLACEX, + 27 + ); + $sPOIPlaceIDs = Result::joinIdsByTableMinRank( + $aRoadPlaceIDs, + Result::TABLE_PLACEX, + 30 + ); - if (!$sPlaceIDs) { + $aIDCondition = array(); + if ($sRoadPlaceIDs) { + $aIDCondition[] = 'parent_place_id in ('.$sRoadPlaceIDs.')'; + } + if ($sPOIPlaceIDs) { + $aIDCondition[] = 'place_id in ('.$sPOIPlaceIDs.')'; + } + + if (empty($aIDCondition)) { return $aResults; } $sHouseNumberRegex = '\\\\m'.$this->sHouseNumber.'\\\\M'; - $sSQL = 'SELECT place_id FROM placex '; - $sSQL .= 'WHERE parent_place_id in ('.$sPlaceIDs.')'; - $sSQL .= " AND housenumber ~* E'".$sHouseNumberRegex."'"; + $sSQL = 'SELECT place_id FROM placex WHERE'; + $sSQL .= " housenumber ~* E'".$sHouseNumberRegex."'"; + $sSQL .= ' AND ('.join(' OR ', $aIDCondition).')'; $sSQL .= $this->oContext->excludeSQL(' AND place_id'); Debug::printSQL($sSQL); @@ -764,11 +782,11 @@ class SearchDescription $bIsIntHouseNumber= (bool) preg_match('/[0-9]+/', $this->sHouseNumber); $iHousenumber = intval($this->sHouseNumber); - if ($bIsIntHouseNumber && empty($aResults)) { + if ($bIsIntHouseNumber && $sRoadPlaceIDs && empty($aResults)) { // if nothing found, search in the interpolation line table $sSQL = 'SELECT distinct place_id FROM location_property_osmline'; $sSQL .= ' WHERE startnumber is not NULL'; - $sSQL .= ' AND parent_place_id in ('.$sPlaceIDs.') AND ('; + $sSQL .= ' AND parent_place_id in ('.$sRoadPlaceIDs.') AND ('; if ($iHousenumber % 2 == 0) { // If housenumber is even, look for housenumber in streets // with interpolationtype even or all. @@ -792,9 +810,9 @@ class SearchDescription } // If nothing found then search in Tiger data (location_property_tiger) - if (CONST_Use_US_Tiger_Data && $bIsIntHouseNumber && empty($aResults)) { + if (CONST_Use_US_Tiger_Data && $sRoadPlaceIDs && $bIsIntHouseNumber && empty($aResults)) { $sSQL = 'SELECT place_id FROM location_property_tiger'; - $sSQL .= ' WHERE parent_place_id in ('.$sPlaceIDs.') and ('; + $sSQL .= ' WHERE parent_place_id in ('.$sRoadPlaceIDs.') and ('; if ($iHousenumber % 2 == 0) { $sSQL .= "interpolationtype='even'"; } else { diff --git a/test/bdd/db/query/search_simple.feature b/test/bdd/db/query/search_simple.feature index 7f141c4c..8c19fb7d 100644 --- a/test/bdd/db/query/search_simple.feature +++ b/test/bdd/db/query/search_simple.feature @@ -45,3 +45,30 @@ Feature: Searching of simple objects Then result addresses contain | amenity | road | | Bean | The build | + + Scenario: when missing housenumbers in search don't return a POI + Given the places + | osm | class | type | name | + | N3 | amenity | restaurant | Wood Street | + And the places + | osm | class | type | name | housenr | + | N20 | amenity | restaurant | Red Way | 34 | + When importing + And sending search query "Wood Street 45" + Then exactly 0 results are returned + When sending search query "Red Way 34" + Then results contain + | osm | + | N20 | + + Scenario: when the housenumber is missing the stret is still returned + Given the grid + | 1 | | 2 | + Given the places + | osm | class | type | name | geometry | + | W1 | highway | residential | Wood Street | 1, 2 | + When importing + And sending search query "Wood Street" + Then results contain + | osm | + | W1 |