]> git.openstreetmap.org Git - nominatim.git/blobdiff - lib/SearchDescription.php
update osm2pgsql (disable install rule)
[nominatim.git] / lib / SearchDescription.php
index 4fafbec2b21c9899fb1e35c51ac8241647876b58..2053082f6bbff4a13bd6a5ba6c08bc89366e0c38 100644 (file)
@@ -2,9 +2,9 @@
 
 namespace Nominatim;
 
 
 namespace Nominatim;
 
-require_once(CONST_BasePath.'/lib/SpecialSearchOperator.php');
-require_once(CONST_BasePath.'/lib/SearchContext.php');
-require_once(CONST_BasePath.'/lib/Result.php');
+require_once(CONST_LibDir.'/SpecialSearchOperator.php');
+require_once(CONST_LibDir.'/SearchContext.php');
+require_once(CONST_LibDir.'/Result.php');
 
 /**
  * Description of a single interpretation of a search query.
 
 /**
  * Description of a single interpretation of a search query.
@@ -21,8 +21,6 @@ class SearchDescription
     private $bRareName = false;
     /// List of word ids making up the address of the object.
     private $aAddress = array();
     private $bRareName = false;
     /// List of word ids making up the address of the object.
     private $aAddress = array();
-    /// Subset of word ids of full words making up the address.
-    private $aFullNameAddress = array();
     /// List of word ids that appear in the name but should be ignored.
     private $aNameNonSearch = array();
     /// List of word ids that appear in the address but should be ignored.
     /// List of word ids that appear in the name but should be ignored.
     private $aNameNonSearch = array();
     /// List of word ids that appear in the address but should be ignored.
@@ -88,18 +86,6 @@ class SearchDescription
         $this->sType = $sType;
     }
 
         $this->sType = $sType;
     }
 
-    /**
-     * Check if this might be a full address search.
-     *
-     * @return bool True if the search contains name, address and housenumber.
-     */
-    public function looksLikeFullAddress()
-    {
-        return (!empty($this->aName))
-               && (!empty($this->aAddress) || $this->sCountryCode)
-               && preg_match('/[0-9]+/', $this->sHouseNumber);
-    }
-
     /**
      * Check if any operator is set.
      *
     /**
      * Check if any operator is set.
      *
@@ -199,15 +185,10 @@ class SearchDescription
         } elseif (($sPhraseType == '' || $sPhraseType == 'postalcode')
                   && is_a($oSearchTerm, '\Nominatim\Token\Postcode')
         ) {
         } elseif (($sPhraseType == '' || $sPhraseType == 'postalcode')
                   && is_a($oSearchTerm, '\Nominatim\Token\Postcode')
         ) {
-            // We need to try the case where the postal code is the primary element
-            // (i.e. no way to tell if it is (postalcode, city) OR (city, postalcode)
-            // so try both.
             if (!$this->sPostcode) {
                 // If we have structured search or this is the first term,
                 // make the postcode the primary search element.
             if (!$this->sPostcode) {
                 // If we have structured search or this is the first term,
                 // make the postcode the primary search element.
-                if ($this->iOperator == Operator::NONE
-                    && ($sPhraseType == 'postalcode' || $bFirstToken)
-                ) {
+                if ($this->iOperator == Operator::NONE && $bFirstToken) {
                     $oSearch = clone $this;
                     $oSearch->iSearchRank++;
                     $oSearch->iOperator = Operator::POSTCODE;
                     $oSearch = clone $this;
                     $oSearch->iSearchRank++;
                     $oSearch->iOperator = Operator::POSTCODE;
@@ -224,6 +205,9 @@ class SearchDescription
                 ) {
                     $oSearch = clone $this;
                     $oSearch->iSearchRank++;
                 ) {
                     $oSearch = clone $this;
                     $oSearch->iSearchRank++;
+                    if (strlen($oSearchTerm->sPostcode) < 4) {
+                        $oSearch->iSearchRank += 4 - strlen($oSearchTerm->sPostcode);
+                    }
                     $oSearch->sPostcode = $oSearchTerm->sPostcode;
                     $aNewSearches[] = $oSearch;
                 }
                     $oSearch->sPostcode = $oSearchTerm->sPostcode;
                     $aNewSearches[] = $oSearch;
                 }
@@ -252,6 +236,19 @@ class SearchDescription
                     $oSearch->iSearchRank++;
                 }
                 $aNewSearches[] = $oSearch;
                     $oSearch->iSearchRank++;
                 }
                 $aNewSearches[] = $oSearch;
+                // Housenumbers may appear in the name when the place has its own
+                // address terms.
+                if ($oSearchTerm->iId !== null
+                    && ($this->iNamePhrase >= 0 || empty($this->aName))
+                    && empty($this->aAddress)
+                   ) {
+                    $oSearch = clone $this;
+                    $oSearch->iSearchRank++;
+                    $oSearch->aAddress = $this->aName;
+                    $oSearch->bRareName = false;
+                    $oSearch->aName = array($oSearchTerm->iId => $oSearchTerm->iId);
+                    $aNewSearches[] = $oSearch;
+                }
             }
         } elseif ($sPhraseType == ''
                   && is_a($oSearchTerm, '\Nominatim\Token\SpecialTerm')
             }
         } elseif ($sPhraseType == ''
                   && is_a($oSearchTerm, '\Nominatim\Token\SpecialTerm')
@@ -288,11 +285,9 @@ class SearchDescription
             if (!empty($this->aName) || !($bFirstPhrase || $sPhraseType == '')) {
                 if (($sPhraseType == '' || !$bFirstPhrase) && !$bHasPartial) {
                     $oSearch = clone $this;
             if (!empty($this->aName) || !($bFirstPhrase || $sPhraseType == '')) {
                 if (($sPhraseType == '' || !$bFirstPhrase) && !$bHasPartial) {
                     $oSearch = clone $this;
-                    $oSearch->iSearchRank += 2;
+                    $oSearch->iSearchRank += 3 * $oSearchTerm->iTermCount;
                     $oSearch->aAddress[$iWordID] = $iWordID;
                     $aNewSearches[] = $oSearch;
                     $oSearch->aAddress[$iWordID] = $iWordID;
                     $aNewSearches[] = $oSearch;
-                } else {
-                    $this->aFullNameAddress[$iWordID] = $iWordID;
                 }
             } else {
                 $oSearch = clone $this;
                 }
             } else {
                 $oSearch = clone $this;
@@ -338,16 +333,19 @@ class SearchDescription
         ) {
             if ($oSearchTerm->iSearchNameCount < CONST_Max_Word_Frequency) {
                 $oSearch = clone $this;
         ) {
             if ($oSearchTerm->iSearchNameCount < CONST_Max_Word_Frequency) {
                 $oSearch = clone $this;
-                $oSearch->iSearchRank += 2;
+                $oSearch->iSearchRank += $oSearchTerm->iTermCount + 1;
+                if (empty($this->aName)) {
+                    $oSearch->iSearchRank++;
+                }
+                if (preg_match('#^[0-9]+$#', $sToken)) {
+                    $oSearch->iSearchRank++;
+                }
                 $oSearch->aAddress[$iWordID] = $iWordID;
                 $aNewSearches[] = $oSearch;
             } else {
                 $oSearch = clone $this;
                 $oSearch->aAddress[$iWordID] = $iWordID;
                 $aNewSearches[] = $oSearch;
             } else {
                 $oSearch = clone $this;
-                $oSearch->iSearchRank++;
+                $oSearch->iSearchRank += $oSearchTerm->iTermCount + 1;
                 $oSearch->aAddressNonSearch[$iWordID] = $iWordID;
                 $oSearch->aAddressNonSearch[$iWordID] = $iWordID;
-                if (preg_match('#^[0-9]+$#', $sToken)) {
-                    $oSearch->iSearchRank += 2;
-                }
                 if (!empty($aFullTokens)) {
                     $oSearch->iSearchRank++;
                 }
                 if (!empty($aFullTokens)) {
                     $oSearch->iSearchRank++;
                 }
@@ -357,7 +355,7 @@ class SearchDescription
                 foreach ($aFullTokens as $oSearchTermToken) {
                     if (is_a($oSearchTermToken, '\Nominatim\Token\Word')) {
                         $oSearch = clone $this;
                 foreach ($aFullTokens as $oSearchTermToken) {
                     if (is_a($oSearchTermToken, '\Nominatim\Token\Word')) {
                         $oSearch = clone $this;
-                        $oSearch->iSearchRank++;
+                        $oSearch->iSearchRank += 3;
                         $oSearch->aAddress[$oSearchTermToken->iId]
                             = $oSearchTermToken->iId;
                         $aNewSearches[] = $oSearch;
                         $oSearch->aAddress[$oSearchTermToken->iId]
                             = $oSearchTermToken->iId;
                         $aNewSearches[] = $oSearch;
@@ -657,13 +655,10 @@ class SearchDescription
         }
 
         if ($this->sHouseNumber) {
         }
 
         if ($this->sHouseNumber) {
-            $aTerms[] = 'address_rank between 16 and 27';
+            $aTerms[] = 'address_rank between 16 and 30';
         } elseif (!$this->sClass || $this->iOperator == Operator::NAME) {
             if ($iMinAddressRank > 0) {
         } elseif (!$this->sClass || $this->iOperator == Operator::NAME) {
             if ($iMinAddressRank > 0) {
-                $aTerms[] = 'address_rank >= '.$iMinAddressRank;
-            }
-            if ($iMaxAddressRank < 30) {
-                $aTerms[] = 'address_rank <= '.$iMaxAddressRank;
+                $aTerms[] = "((address_rank between $iMinAddressRank and $iMaxAddressRank) or (search_rank between $iMinAddressRank and $iMaxAddressRank))";
             }
         }
 
             }
         }
 
@@ -699,10 +694,11 @@ class SearchDescription
         $sImportanceSQL .= $this->oContext->viewboxImportanceSQL('centroid');
         $aOrder[] = "$sImportanceSQL DESC";
 
         $sImportanceSQL .= $this->oContext->viewboxImportanceSQL('centroid');
         $aOrder[] = "$sImportanceSQL DESC";
 
-        if (!empty($this->aFullNameAddress)) {
+        $aFullNameAddress = $this->oContext->getFullNameTerms();
+        if (!empty($aFullNameAddress)) {
             $sExactMatchSQL = ' ( ';
             $sExactMatchSQL .= ' SELECT count(*) FROM ( ';
             $sExactMatchSQL = ' ( ';
             $sExactMatchSQL .= ' SELECT count(*) FROM ( ';
-            $sExactMatchSQL .= '  SELECT unnest('.$oDB->getArraySQL($this->aFullNameAddress).')';
+            $sExactMatchSQL .= '  SELECT unnest('.$oDB->getArraySQL($aFullNameAddress).')';
             $sExactMatchSQL .= '    INTERSECT ';
             $sExactMatchSQL .= '  SELECT unnest(nameaddress_vector)';
             $sExactMatchSQL .= ' ) s';
             $sExactMatchSQL .= '    INTERSECT ';
             $sExactMatchSQL .= '  SELECT unnest(nameaddress_vector)';
             $sExactMatchSQL .= ' ) s';
@@ -1019,7 +1015,7 @@ class SearchDescription
                 'Name terms (stop words)' => $this->aNameNonSearch,
                 'Address terms' => $this->aAddress,
                 'Address terms (stop words)' => $this->aAddressNonSearch,
                 'Name terms (stop words)' => $this->aNameNonSearch,
                 'Address terms' => $this->aAddress,
                 'Address terms (stop words)' => $this->aAddressNonSearch,
-                'Address terms (full words)' => $this->aFullNameAddress,
+                'Address terms (full words)' => $this->aFullNameAddress ?? '',
                 'Special search' => $this->iOperator,
                 'Class' => $this->sClass,
                 'Type' => $this->sType,
                 'Special search' => $this->iOperator,
                 'Class' => $this->sClass,
                 'Type' => $this->sType,
@@ -1031,7 +1027,7 @@ class SearchDescription
     public function dumpAsHtmlTableRow(&$aWordIDs)
     {
         $kf = function ($k) use (&$aWordIDs) {
     public function dumpAsHtmlTableRow(&$aWordIDs)
     {
         $kf = function ($k) use (&$aWordIDs) {
-            return $aWordIDs[$k];
+            return $aWordIDs[$k] ?? '['.$k.']';
         };
 
         echo '<tr>';
         };
 
         echo '<tr>';