]> git.openstreetmap.org Git - nominatim.git/commitdiff
Add result ranking for missing housenumber and postcode
authorSarah Hoffmann <lonvia@denofr.de>
Fri, 16 Nov 2018 22:52:19 +0000 (23:52 +0100)
committerSarah Hoffmann <lonvia@denofr.de>
Fri, 16 Nov 2018 23:00:01 +0000 (00:00 +0100)
Fixes #988.

lib/Geocode.php
lib/Result.php
lib/SearchDescription.php

index f0e03de5f3e75c1b8e4b81ba458963c94b8828b9..e2fd7272c34db0deb4220d1ef83a6d95b6dbf9da 100644 (file)
@@ -546,7 +546,6 @@ class Geocode
         // Do we have anything that looks like a lat/lon pair?
         $sQuery = $oCtx->setNearPointFromQuery($sQuery);
 
-        $aResults = array();
         if ($sQuery || $this->aStructuredQuery) {
             // Start with a single blank search
             $aSearches = array(new SearchDescription($oCtx));
@@ -746,8 +745,10 @@ class Geocode
             // Start the search process
             $iGroupLoop = 0;
             $iQueryLoop = 0;
+            $aNextResults = array();
             foreach ($aGroupedSearches as $iGroupedRank => $aSearches) {
                 $iGroupLoop++;
+                $aResults = $aNextResults;
                 foreach ($aSearches as $oSearch) {
                     $iQueryLoop++;
 
@@ -767,6 +768,23 @@ class Geocode
                     if ($iQueryLoop > 20) break;
                 }
 
+                if (!empty($aResults)) {
+                    $aSplitResults = Result::splitResults($aResults);
+                    Debug::printVar('Split results', $aSplitResults);
+                    if ($iGroupLoop <= 4 && empty($aSplitResults['tail'])
+                        && reset($aSplitResults['head'])->iResultRank > 0) {
+                        // Haven't found an exact match for the query yet.
+                        // Therefore add result from the next group level.
+                        $aNextResults = $aSplitResults['head'];
+                        foreach ($aNextResults as $oRes) {
+                            $oRes->iResultRank--;
+                        }
+                        $aResults = array();
+                    } else {
+                        $aResults = $aSplitResults['head'];
+                    }
+                }
+
                 if (!empty($aResults) && ($this->iMinAddressRank != 0 || $this->iMaxAddressRank != 30)) {
                     // Need to verify passes rank limits before dropping out of the loop (yuk!)
                     // reduces the number of place ids, like a filter
index d69ac62f1f7b28cc731a49146b830a59f0323f05..5c39f473746b1dffd7d9ffd93d7343a73b59c750 100644 (file)
@@ -68,4 +68,32 @@ class Result
 
         return $sHousenumbers;
     }
+
+    /**
+     * Split a result array into highest ranked result and the rest
+     *
+     * @param object[] $aResults  List of results to split.
+     *
+     * @return array[]
+     */
+    public static function splitResults($aResults)
+    {
+        $aHead = array();
+        $aTail = array();
+        $iMinRank = 10000;
+
+        foreach ($aResults as $oRes) {
+            if ($oRes->iResultRank < $iMinRank) {
+                $aTail = array_merge($aTail, $aHead);
+                $aHead = array($oRes->iId => $oRes);
+                $iMinRank = $oRes->iResultRank;
+            } elseif ($oRes->iResultRank == $iMinRank) {
+                $aHead[$oRes->iId] = $oRes;
+            } else {
+                $aTail[$oRes->iId] = $oRes;
+            }
+        }
+
+        return array('head' => $aHead, 'tail' => $aTail);
+    }
 }
index ec14e54600ee11f106d83b54ab6510b9b98be708..204a735885f8d3222e6ab1b5236e91f7f87a712f 100644 (file)
@@ -453,6 +453,9 @@ class SearchDescription
 
                 if (empty($aResults) && $this->looksLikeFullAddress()) {
                     $aResults = $aNamedPlaceIDs;
+                    foreach ($aResults as $oRes) {
+                        $oRes->iResultRank++;
+                    }
                 }
             }
 
@@ -469,16 +472,13 @@ class SearchDescription
             if ($sPlaceIds) {
                 $sSQL = 'SELECT place_id FROM placex';
                 $sSQL .= ' WHERE place_id in ('.$sPlaceIds.')';
-                $sSQL .= " AND postcode = '".$this->sPostcode."'";
+                $sSQL .= " AND postcode != '".$this->sPostcode."'";
                 Debug::printSQL($sSQL);
                 $aFilteredPlaceIDs = chksql($oDB->getCol($sSQL));
                 if ($aFilteredPlaceIDs) {
-                    $aNewResults = array();
                     foreach ($aFilteredPlaceIDs as $iPlaceId) {
-                        $aNewResults[$iPlaceId] = $aResults[$iPlaceId];
+                        $aResults[$iPlaceId]->iResultRank++;
                     }
-                    $aResults = $aNewResults;
-                    Debug::printVar('Place IDs after postcode filtering', $aResults);
                 }
             }
         }