mirror of
https://github.com/osm-search/Nominatim.git
synced 2026-02-16 15:47:58 +00:00
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.
This commit is contained in:
@@ -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)
|
public static function sqlHouseNumberTable($aResults, $iTable)
|
||||||
{
|
{
|
||||||
$sHousenumbers = '';
|
$sHousenumbers = '';
|
||||||
|
|||||||
@@ -447,23 +447,24 @@ class SearchDescription
|
|||||||
|
|
||||||
// Now search for housenumber, if housenumber provided. Can be zero.
|
// Now search for housenumber, if housenumber provided. Can be zero.
|
||||||
if (($this->sHouseNumber || $this->sHouseNumber === '0') && !empty($aResults)) {
|
if (($this->sHouseNumber || $this->sHouseNumber === '0') && !empty($aResults)) {
|
||||||
// Downgrade the rank of the street results, they are missing
|
|
||||||
// the housenumber.
|
|
||||||
foreach ($aResults as $oRes) {
|
|
||||||
if ($oRes->iAddressRank >= 26) {
|
|
||||||
$oRes->iResultRank++;
|
|
||||||
} else {
|
|
||||||
$oRes->iResultRank += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$aHnResults = $this->queryHouseNumber($oDB, $aResults);
|
$aHnResults = $this->queryHouseNumber($oDB, $aResults);
|
||||||
|
|
||||||
if (!empty($aHnResults)) {
|
// Downgrade the rank of the street results, they are missing
|
||||||
foreach ($aHnResults as $oRes) {
|
// the housenumber. Also drop POI places (rank 30) here, they
|
||||||
$aResults[$oRes->iId] = $oRes;
|
// 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 < 28) {
|
||||||
|
if ($oRes->iAddressRank >= 26) {
|
||||||
|
$oRes->iResultRank++;
|
||||||
|
} else {
|
||||||
|
$oRes->iResultRank += 2;
|
||||||
|
}
|
||||||
|
$aHnResults[$oRes->iId] = $oRes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$aResults = $aHnResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally get POIs if requested
|
// finally get POIs if requested
|
||||||
@@ -743,16 +744,33 @@ class SearchDescription
|
|||||||
private function queryHouseNumber(&$oDB, $aRoadPlaceIDs)
|
private function queryHouseNumber(&$oDB, $aRoadPlaceIDs)
|
||||||
{
|
{
|
||||||
$aResults = array();
|
$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;
|
return $aResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sHouseNumberRegex = '\\\\m'.$this->sHouseNumber.'\\\\M';
|
$sHouseNumberRegex = '\\\\m'.$this->sHouseNumber.'\\\\M';
|
||||||
$sSQL = 'SELECT place_id FROM placex ';
|
$sSQL = 'SELECT place_id FROM placex WHERE';
|
||||||
$sSQL .= 'WHERE parent_place_id in ('.$sPlaceIDs.')';
|
$sSQL .= " housenumber ~* E'".$sHouseNumberRegex."'";
|
||||||
$sSQL .= " AND housenumber ~* E'".$sHouseNumberRegex."'";
|
$sSQL .= ' AND ('.join(' OR ', $aIDCondition).')';
|
||||||
$sSQL .= $this->oContext->excludeSQL(' AND place_id');
|
$sSQL .= $this->oContext->excludeSQL(' AND place_id');
|
||||||
|
|
||||||
Debug::printSQL($sSQL);
|
Debug::printSQL($sSQL);
|
||||||
@@ -764,11 +782,11 @@ class SearchDescription
|
|||||||
|
|
||||||
$bIsIntHouseNumber= (bool) preg_match('/[0-9]+/', $this->sHouseNumber);
|
$bIsIntHouseNumber= (bool) preg_match('/[0-9]+/', $this->sHouseNumber);
|
||||||
$iHousenumber = intval($this->sHouseNumber);
|
$iHousenumber = intval($this->sHouseNumber);
|
||||||
if ($bIsIntHouseNumber && empty($aResults)) {
|
if ($bIsIntHouseNumber && $sRoadPlaceIDs && empty($aResults)) {
|
||||||
// if nothing found, search in the interpolation line table
|
// if nothing found, search in the interpolation line table
|
||||||
$sSQL = 'SELECT distinct place_id FROM location_property_osmline';
|
$sSQL = 'SELECT distinct place_id FROM location_property_osmline';
|
||||||
$sSQL .= ' WHERE startnumber is not NULL';
|
$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 ($iHousenumber % 2 == 0) {
|
||||||
// If housenumber is even, look for housenumber in streets
|
// If housenumber is even, look for housenumber in streets
|
||||||
// with interpolationtype even or all.
|
// with interpolationtype even or all.
|
||||||
@@ -792,9 +810,9 @@ class SearchDescription
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If nothing found then search in Tiger data (location_property_tiger)
|
// 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 = '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) {
|
if ($iHousenumber % 2 == 0) {
|
||||||
$sSQL .= "interpolationtype='even'";
|
$sSQL .= "interpolationtype='even'";
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -45,3 +45,30 @@ Feature: Searching of simple objects
|
|||||||
Then result addresses contain
|
Then result addresses contain
|
||||||
| amenity | road |
|
| amenity | road |
|
||||||
| Bean | The build |
|
| 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 |
|
||||||
|
|||||||
Reference in New Issue
Block a user