From: Sarah Hoffmann Date: Thu, 5 Oct 2017 22:14:48 +0000 (+0200) Subject: move initial search setup to new class type X-Git-Tag: v3.1.0~47^2~17 X-Git-Url: https://git.openstreetmap.org./nominatim.git/commitdiff_plain/0067555c38cece9cf11a0074ab59456c22c8c97d move initial search setup to new class type --- diff --git a/lib/Geocode.php b/lib/Geocode.php index a403fa10..88a969a5 100644 --- a/lib/Geocode.php +++ b/lib/Geocode.php @@ -1023,76 +1023,59 @@ class Geocode $aSearchResults = array(); if ($sQuery || $this->aStructuredQuery) { - // Start with a blank search - $aSearches = array( - array( - 'iSearchRank' => 0, - 'iNamePhrase' => -1, - 'sCountryCode' => false, - 'aName' => array(), - 'aAddress' => array(), - 'aFullNameAddress' => array(), - 'aNameNonSearch' => array(), - 'aAddressNonSearch' => array(), - 'sOperator' => '', - 'aFeatureName' => array(), - 'sClass' => '', - 'sType' => '', - 'sHouseNumber' => '', - 'sPostcode' => '', - 'oNear' => $oNearPoint - ) - ); - - // Any 'special' terms in the search? - $bSpecialTerms = false; - preg_match_all('/\\[([\\w_]*)=([\\w_]*)\\]/', $sQuery, $aSpecialTermsRaw, PREG_SET_ORDER); - foreach ($aSpecialTermsRaw as $aSpecialTerm) { - $sQuery = str_replace($aSpecialTerm[0], ' ', $sQuery); - if (!$bSpecialTerms) { - $aNewSearches = array(); - foreach ($aSearches as $aSearch) { - $aNewSearch = $aSearch; - $aNewSearch['sClass'] = $aSpecialTerm[1]; - $aNewSearch['sType'] = $aSpecialTerm[2]; - $aNewSearches[] = $aNewSearch; - } + // Start with a single blank search + $aSearches = array(new SearchDescription()); - $aSearches = $aNewSearches; - $bSpecialTerms = true; - } + if ($oNearPoint) { + $aSearches[0]->setNear($oNearPoint); } - preg_match_all('/\\[([\\w ]*)\\]/u', $sQuery, $aSpecialTermsRaw, PREG_SET_ORDER); - if (isset($this->aStructuredQuery['amenity']) && $this->aStructuredQuery['amenity']) { - $aSpecialTermsRaw[] = array('['.$this->aStructuredQuery['amenity'].']', $this->aStructuredQuery['amenity']); - unset($this->aStructuredQuery['amenity']); + if ($sQuery) { + $sQuery = $aSearches[0]->extractKeyValuePairs($sQuery); } - foreach ($aSpecialTermsRaw as $aSpecialTerm) { - $sQuery = str_replace($aSpecialTerm[0], ' ', $sQuery); - if ($bSpecialTerms) { - continue; + $sSpecialTerm = ''; + if ($sQuery) { + preg_match_all( + '/\\[([\\w ]*)\\]/u', + $sQuery, + $aSpecialTermsRaw, + PREG_SET_ORDER + ); + foreach ($aSpecialTermsRaw as $aSpecialTerm) { + $sQuery = str_replace($aSpecialTerm[0], ' ', $sQuery); + if (!$sSpecialTerm) { + $sSpecialTerm = $aSpecialTerm[1]; + } } + } + if (!$sSpecialTerm && $this->aStructuredQuery + && isset($this->aStructuredQuery['amenity'])) { + $sSpecialTerm = $this->aStructuredQuery['amenity']; + unset($this->aStructuredQuery['amenity']); + } - $sToken = chksql($this->oDB->getOne("SELECT make_standard_name('".pg_escape_string($aSpecialTerm[1])."') AS string")); - $sSQL = 'SELECT * '; - $sSQL .= 'FROM ( '; - $sSQL .= ' SELECT word_id, word_token, word, class, type, country_code, operator'; - $sSQL .= ' FROM word '; + if ($sSpecialTerm && !$aSearches[0]->hasOperator()) { + $sSpecialTerm = pg_escape_string($sSpecialTerm); + $sToken = chksql( + $this->oDB->getOne("SELECT make_standard_name('$sSpecialTerm')"), + "Cannot decode query. Wrong encoding?" + ); + $sSQL = 'SELECT class, type FROM word '; $sSQL .= ' WHERE word_token in (\' '.$sToken.'\')'; - $sSQL .= ') AS x '; - $sSQL .= ' WHERE (class is not null AND class not in (\'place\'))'; + $sSQL .= ' AND class is not null AND class not in (\'place\')'; if (CONST_Debug) var_Dump($sSQL); $aSearchWords = chksql($this->oDB->getAll($sSQL)); $aNewSearches = array(); - foreach ($aSearches as $aSearch) { + foreach ($aSearches as $oSearch) { foreach ($aSearchWords as $aSearchTerm) { - $aNewSearch = $aSearch; - $aNewSearch['sClass'] = $aSearchTerm['class']; - $aNewSearch['sType'] = $aSearchTerm['type']; - $aNewSearches[] = $aNewSearch; - $bSpecialTerms = true; + $oNewSearch = clone $oSearch; + $oNewSearch->setPoiSearch( + Operator::TYPE, + $aSearchTerm['class'], + $aSearchTerm['type'], + ); + $aNewSearches[] = $oNewSearch; } } $aSearches = $aNewSearches; @@ -1212,10 +1195,10 @@ class Geocode foreach ($aGroupedSearches as $aSearches) { foreach ($aSearches as $aSearch) { - if ($aSearch['iSearchRank'] < $this->iMaxRank) { - if (!isset($aReverseGroupedSearches[$aSearch['iSearchRank']])) $aReverseGroupedSearches[$aSearch['iSearchRank']] = array(); - $aReverseGroupedSearches[$aSearch['iSearchRank']][] = $aSearch; + if (!isset($aReverseGroupedSearches[$aSearch->getRank()])) { + $aReverseGroupedSearches[$aSearch->getRank()] = array(); } + $aReverseGroupedSearches[$aSearch->getRank()][] = $aSearch; } } @@ -1226,9 +1209,9 @@ class Geocode // Re-group the searches by their score, junk anything over 20 as just not worth trying $aGroupedSearches = array(); foreach ($aSearches as $aSearch) { - if ($aSearch['iSearchRank'] < $this->iMaxRank) { - if (!isset($aGroupedSearches[$aSearch['iSearchRank']])) $aGroupedSearches[$aSearch['iSearchRank']] = array(); - $aGroupedSearches[$aSearch['iSearchRank']][] = $aSearch; + if ($aSearch->getRank() < $this->iMaxRank) { + if (!isset($aGroupedSearches[$aSearch->getRank()])) $aGroupedSearches[$aSearch->getRank()] = array(); + $aGroupedSearches[$aSearch->getRank()][] = $aSearch; } } ksort($aGroupedSearches); diff --git a/lib/SearchDescription.php b/lib/SearchDescription.php index e46dc464..f2785c1e 100644 --- a/lib/SearchDescription.php +++ b/lib/SearchDescription.php @@ -8,15 +8,17 @@ namespace Nominatim; abstract final class Operator { /// No operator selected. - const NONE = -1; + const NONE = 0; + /// Search for POI of the given type. + const TYPE = 1; /// Search for POIs near the given place. - const NEAR = 0; + const NEAR = 2; /// Search for POIS in the given place. - const IN = 1; + const IN = 3; /// Search for POIS named as given. - const NAME = 3; + const NAME = 4; /// Search for postcodes. - const POSTCODE = 4; + const POSTCODE = 5; } /** @@ -55,4 +57,56 @@ class SearchDescription /// Index of phrase currently processed private $iNamePhrase = -1; + + public getRank() + { + return $this->iSearchRank; + } + + /** + * Set the geographic search radius. + */ + public setNear(&$oNearPoint) + { + $this->oNearPoint = $oNearPoint; + } + + public setPoiSearch($iOperator, $sClass, $sType) + { + $this->iOperator = $iOperator; + $this->sClass = $sClass; + $this->sType = $sType; + } + + public hasOperator() + { + return $this->iOperator != Operator::NONE; + } + + /** + * Extract special terms from the query, amend the search + * and return the shortended query. + * + * Only the first special term found will be used but all will + * be removed from the query. + */ + public extractKeyValuePairs(&$oDB, $sQuery) + { + // Search for terms of kind [=]. + preg_match_all( + '/\\[([\\w_]*)=([\\w_]*)\\]/', + $sQuery, + $aSpecialTermsRaw, + PREG_SET_ORDER + ); + + foreach ($aSpecialTermsRaw as $aTerm) { + $sQuery = str_replace($aTerm[0], ' ', $sQuery); + if (!$this->hasOperator()) { + $this->setPoiSearch(Operator::TYPE, $aTerm[1], $aTerm[2]); + } + } + + return $sQuery; + } };