X-Git-Url: https://git.openstreetmap.org/nominatim.git/blobdiff_plain/f9517e91433a9f33a01f75efe3629330196f21f5..500c61685b16fd1d51e7b5f4738c788a9d00eab4:/lib-php/SearchDescription.php diff --git a/lib-php/SearchDescription.php b/lib-php/SearchDescription.php index 2b39443f..6091fd61 100644 --- a/lib-php/SearchDescription.php +++ b/lib-php/SearchDescription.php @@ -153,8 +153,6 @@ class SearchDescription * Derive new searches by adding a full term to the existing search. * * @param object $oSearchTerm Description of the token. - * @param bool $bHasPartial True if there are also tokens of partial terms - * with the same name. * @param string $sPhraseType Type of phrase the token is contained in. * @param bool $bFirstToken True if the token is at the beginning of the * query. @@ -164,7 +162,7 @@ class SearchDescription * * @return SearchDescription[] List of derived search descriptions. */ - public function extendWithFullTerm($oSearchTerm, $bHasPartial, $sPhraseType, $bFirstToken, $bFirstPhrase, $bLastToken) + public function extendWithFullTerm($oSearchTerm, $sPhraseType, $bFirstToken, $bFirstPhrase, $bLastToken) { $aNewSearches = array(); @@ -218,30 +216,33 @@ class SearchDescription && is_a($oSearchTerm, '\Nominatim\Token\HouseNumber') ) { if (!$this->sHouseNumber && $this->iOperator != Operator::POSTCODE) { - $oSearch = clone $this; - $oSearch->iSearchRank++; - $oSearch->iNamePhrase = -1; - $oSearch->sHouseNumber = $oSearchTerm->sToken; - if ($this->iOperator != Operator::NONE) { - $oSearch->iSearchRank++; - } // sanity check: if the housenumber is not mainly made // up of numbers, add a penalty - if (preg_match('/\\d/', $oSearch->sHouseNumber) === 0 - || preg_match_all('/[^0-9]/', $oSearch->sHouseNumber, $aMatches) > 2) { - $oSearch->iSearchRank++; + $iSearchCost = 1; + if (preg_match('/\\d/', $oSearchTerm->sToken) === 0 + || preg_match_all('/[^0-9]/', $oSearchTerm->sToken, $aMatches) > 2) { + $iSearchCost++; + } + if ($this->iOperator != Operator::NONE) { + $iSearchCost++; } if (empty($oSearchTerm->iId)) { - $oSearch->iSearchRank++; + $iSearchCost++; } // also must not appear in the middle of the address if (!empty($this->aAddress) || (!empty($this->aAddressNonSearch)) || $this->sPostcode ) { - $oSearch->iSearchRank++; + $iSearchCost++; } + + $oSearch = clone $this; + $oSearch->iSearchRank += $iSearchCost; + $oSearch->iNamePhrase = -1; + $oSearch->sHouseNumber = $oSearchTerm->sToken; $aNewSearches[] = $oSearch; + // Housenumbers may appear in the name when the place has its own // address terms. if ($oSearchTerm->iId !== null @@ -249,7 +250,7 @@ class SearchDescription && empty($this->aAddress) ) { $oSearch = clone $this; - $oSearch->iSearchRank++; + $oSearch->iSearchRank += $iSearchCost; $oSearch->aAddress = $this->aName; $oSearch->bRareName = false; $oSearch->aName = array($oSearchTerm->iId => $oSearchTerm->iId); @@ -295,10 +296,10 @@ class SearchDescription // the first phrase. In unstructured search it may be in a later // phrase when the first phrase is a house number. if (!empty($this->aName) || !($bFirstPhrase || $sPhraseType == '')) { - if (($sPhraseType == '' || !$bFirstPhrase) && !$bHasPartial) { + if (($sPhraseType == '' || !$bFirstPhrase) && $oSearchTerm->iTermCount > 1) { $oSearch = clone $this; $oSearch->iNamePhrase = -1; - $oSearch->iSearchRank += 3 * $oSearchTerm->iTermCount; + $oSearch->iSearchRank += 1; $oSearch->aAddress[$iWordID] = $iWordID; $aNewSearches[] = $oSearch; } @@ -333,7 +334,9 @@ class SearchDescription public function extendWithPartialTerm($sToken, $oSearchTerm, $bStructuredPhrases, $iPhrase, $aFullTokens) { // Only allow name terms. - if (!(is_a($oSearchTerm, '\Nominatim\Token\Word'))) { + if (!(is_a($oSearchTerm, '\Nominatim\Token\Word')) + || strpos($sToken, ' ') !== false + ) { return array(); } @@ -361,7 +364,6 @@ class SearchDescription if ((!$this->sPostcode && !$this->aAddress && !$this->aAddressNonSearch) && ((empty($this->aName) && empty($this->aNameNonSearch)) || $this->iNamePhrase == $iPhrase) - && strpos($sToken, ' ') === false ) { $oSearch = clone $this; $oSearch->iSearchRank++; @@ -413,7 +415,6 @@ class SearchDescription public function query(&$oDB, $iMinRank, $iMaxRank, $iLimit) { $aResults = array(); - $iHousenumber = -1; if ($this->sCountryCode && empty($this->aName) @@ -446,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 @@ -621,7 +623,7 @@ class SearchDescription $aOrder[0] .= ' SELECT place_id'; $aOrder[0] .= ' FROM placex'; $aOrder[0] .= ' WHERE parent_place_id = search_name.place_id'; - $aOrder[0] .= " AND transliteration(housenumber) ~* E'".$sHouseNumberRegex."'"; + $aOrder[0] .= " AND housenumber ~* E'".$sHouseNumberRegex."'"; $aOrder[0] .= ' LIMIT 1'; $aOrder[0] .= ') '; // also housenumbers from interpolation lines table are needed @@ -742,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 transliteration(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); @@ -763,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. @@ -790,24 +809,10 @@ class SearchDescription } } - // If nothing found try the aux fallback table - if (CONST_Use_Aux_Location_data && empty($aResults)) { - $sSQL = 'SELECT place_id FROM location_property_aux'; - $sSQL .= ' WHERE parent_place_id in ('.$sPlaceIDs.')'; - $sSQL .= " AND housenumber = '".$this->sHouseNumber."'"; - $sSQL .= $this->oContext->excludeSQL(' AND place_id'); - - Debug::printSQL($sSQL); - - foreach ($oDB->getCol($sSQL) as $iPlaceId) { - $aResults[$iPlaceId] = new Result($iPlaceId, Result::TABLE_AUX); - } - } - // 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 {