]> git.openstreetmap.org Git - nominatim.git/commitdiff
move initial search setup to new class type
authorSarah Hoffmann <lonvia@denofr.de>
Thu, 5 Oct 2017 22:14:48 +0000 (00:14 +0200)
committerSarah Hoffmann <lonvia@denofr.de>
Sat, 7 Oct 2017 10:24:21 +0000 (12:24 +0200)
lib/Geocode.php
lib/SearchDescription.php

index a403fa1080c8755e75c9691a6e6ad41dd47e803e..88a969a54b93a6e324703e01fc4e033af5abb403 100644 (file)
@@ -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);
index e46dc4642728fac0f6ac670aba142fa1e4e2a1e9..f2785c1e4c2343d4f906c5daf0224a293a3485c6 100644 (file)
@@ -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 [<key>=<value>].
+        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;
+    }
 };