EBernhardson has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/227501

Change subject: Move query rewriting into search backend
......................................................................

Move query rewriting into search backend

We want to expose this query rewriting behavior to both api and
web requests. Additionally we want to be able to test different
configurations of the query suggestions.  This patch allows for
both by moving the rewriting from core into the search engine.

Bug: T106888
Change-Id: I0a8f75759f9148f53358707369b8a7128215de86
---
M includes/api/ApiQuerySearch.php
M includes/search/SearchResultSet.php
M includes/specials/SpecialSearch.php
M tests/phpunit/includes/specials/SpecialSearchTest.php
4 files changed, 66 insertions(+), 61 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/01/227501/1

diff --git a/includes/api/ApiQuerySearch.php b/includes/api/ApiQuerySearch.php
index 349e7fa..de905a3 100644
--- a/includes/api/ApiQuerySearch.php
+++ b/includes/api/ApiQuerySearch.php
@@ -198,6 +198,9 @@
                                if ( isset( $prop['isfilematch'] ) ) {
                                        $vals['isfilematch'] = 
$result->isFileMatch();
                                }
+                               if ( isset( $prop['rewrittenquery'] ) ) {
+                                       $vals['rewrittenquery'] = 
$result->getRewrittenQuery();
+                               }
 
                                // Add item to results and see whether it fits
                                $fit = $apiResult->addValue( array( 'query', 
$this->getModuleName() ),
@@ -311,7 +314,7 @@
                                ApiBase::PARAM_ISMULTI => true,
                        ),
                        'prop' => array(
-                               ApiBase::PARAM_DFLT => 
'size|wordcount|timestamp|snippet',
+                               ApiBase::PARAM_DFLT => 
'size|wordcount|timestamp|snippet|rewrittenquery',
                                ApiBase::PARAM_TYPE => array(
                                        'size',
                                        'wordcount',
@@ -326,6 +329,7 @@
                                        'hasrelated',
                                        'isfilematch',
                                        'categorysnippet',
+                                       'rewrittenquery',
                                ),
                                ApiBase::PARAM_ISMULTI => true,
                        ),
diff --git a/includes/search/SearchResultSet.php 
b/includes/search/SearchResultSet.php
index 0a05eef..98fd51e 100644
--- a/includes/search/SearchResultSet.php
+++ b/includes/search/SearchResultSet.php
@@ -61,6 +61,33 @@
        }
 
        /**
+        * Some search modes will run an alternative query that it thinks gives
+        * a better result than the provided search. Returns true if this has
+        * occured.
+        *
+        * @return bool
+        */
+       function hasRewrittenQuery() {
+               return false;
+       }
+
+       /**
+        * @return string|null The search the query was internally rewritten to,
+        *  or null when the result of the original query was returned.
+        */
+       function getQueryAfterRewrite() {
+               return null;
+       }
+
+       /**
+        * @return string|null Same as self::getQueryAfterRewrite(), but in HTML
+        *  and with changes highlighted. Nul when the query was not rewritten.
+        */
+       function getQueryAfterRewriteSnippet() {
+               return null;
+       }
+
+       /**
         * Some search modes return a suggested alternate term if there are
         * no exact hits. Returns true if there is one on this set.
         *
diff --git a/includes/specials/SpecialSearch.php 
b/includes/specials/SpecialSearch.php
index 84077e6..23940d8 100644
--- a/includes/specials/SpecialSearch.php
+++ b/includes/specials/SpecialSearch.php
@@ -216,6 +216,7 @@
                global $wgContLang;
 
                $search = $this->getSearchEngine();
+               $search->setFeatureData( 'disableRewrites', 
!$this->runSuggestion );
                $search->setLimitOffset( $this->limit, $this->offset );
                $search->setNamespaces( $this->namespaces );
                $search->prefix = $this->mPrefix;
@@ -272,12 +273,8 @@
                // did you mean... suggestions
                $didYouMeanHtml = '';
                if ( $showSuggestion && $textMatches && !$textStatus ) {
-                       if ( $this->shouldRunSuggestedQuery( $textMatches ) ) {
-                               $newMatches = $search->searchText( 
$textMatches->getSuggestionQuery() );
-                               if ( $newMatches instanceof SearchResultSet && 
$newMatches->numRows() > 0 ) {
-                                       $didYouMeanHtml = 
$this->getDidYouMeanRewrittenHtml( $term, $textMatches );
-                                       $textMatches = $newMatches;
-                               }
+                       if ( $textMatches->hasRewrittenQuery() ) {
+                               $didYouMeanHtml = 
$this->getDidYouMeanRewrittenHtml( $term, $textMatches );
                        } elseif ( $textMatches->hasSuggestion() ) {
                                $didYouMeanHtml = $this->getDidYouMeanHtml( 
$textMatches );
                        }
@@ -401,30 +398,6 @@
        }
 
        /**
-        * Decide if the suggested query should be run, and it's results 
returned
-        * instead of the provided $textMatches
-        *
-        * @param SearchResultSet $textMatches The results of a users query
-        * @return bool
-        */
-       protected function shouldRunSuggestedQuery( SearchResultSet 
$textMatches ) {
-               global $wgSearchRunSuggestedQueryPercent;
-
-               if ( !$this->runSuggestion ||
-                       !$textMatches->hasSuggestion() ||
-                       $textMatches->numRows() > 0 ||
-                       $textMatches->searchContainedSyntax()
-               ) {
-                       return false;
-               }
-
-               // Generate a random number between 0 and 1. If the
-               // number is less than the desired percentages run it.
-               $rand = rand( 0, getrandmax() ) / getrandmax();
-               return $wgSearchRunSuggestedQueryPercent > $rand;
-       }
-
-       /**
         * Generates HTML shown to the user when we have a suggestion about a 
query
         * that might give more results than their current query.
         */
@@ -464,7 +437,7 @@
                // Showing results for '$rewritten'
                // Search instead for '$orig'
 
-               $params = array( 'search' => $textMatches->getSuggestionQuery() 
);
+               $params = array( 'search' => 
$textMatches->getQueryAfterRewrite() );
                if ( $this->fulltext != null ) {
                        $params['fulltext'] = $this->fulltext;
                }
@@ -472,7 +445,7 @@
 
                $rewritten = Linker::linkKnown(
                        $this->getPageTitle(),
-                       $textMatches->getSuggestionSnippet() ?: null,
+                       $textMatches->getQueryAfterRewriteSnippet() ?: null,
                        array(),
                        $stParams
                );
diff --git a/tests/phpunit/includes/specials/SpecialSearchTest.php 
b/tests/phpunit/includes/specials/SpecialSearchTest.php
index 7e60fdd..13c2838 100644
--- a/tests/phpunit/includes/specials/SpecialSearchTest.php
+++ b/tests/phpunit/includes/specials/SpecialSearchTest.php
@@ -145,34 +145,25 @@
        public function provideRewriteQueryWithSuggestion() {
                return array(
                        array(
-                               'With results and a suggestion does not run 
suggested query',
+                               'With suggestion and no rewritten query shows 
did you mean',
                                '/Did you mean: <a[^>]+>first suggestion/',
-                               array(
-                                       new SpecialSearchTestMockResultSet( 
'first suggestion', array(
-                                               SearchResult::newFromTitle( 
Title::newMainPage() ),
-                                       ) ),
-                                       new SpecialSearchTestMockResultSet( 
'was never run', array() ),
-                               ),
+                               new SpecialSearchTestMockResultSet( 'first 
suggestion', null, array(
+                                       SearchResult::newFromTitle( 
Title::newMainPage() ),
+                               ) ),
                        ),
 
                        array(
-                               'With no results and a suggestion responds with 
suggested query results',
+                               'With rewritten query informs user of change',
                                '/Showing results for <a[^>]+>first 
suggestion/',
-                               array(
-                                       new SpecialSearchTestMockResultSet( 
'first suggestion', array() ),
-                                       new SpecialSearchTestMockResultSet( 
'second suggestion', array(
-                                               SearchResult::newFromTitle( 
Title::newMainPage() ),
-                                       ) ),
-                               ),
+                               new SpecialSearchTestMockResultSet( 'asdf', 
'first suggestion', array(
+                                       SearchResult::newFromTitle( 
Title::newMainPage() ),
+                               ) ),
                        ),
 
                        array(
                                'When both queries have no results user gets no 
results',
                                '/There were no results matching the query/',
-                               array(
-                                       new SpecialSearchTestMockResultSet( 
'first suggestion', array() ),
-                                       new SpecialSearchTestMockResultSet( 
'second suggestion', array() ),
-                               ),
+                               new SpecialSearchTestMockResultSet( 'first 
suggestion', 'first suggestion', array() ),
                        ),
                );
        }
@@ -180,8 +171,8 @@
        /**
         * @dataProvider provideRewriteQueryWithSuggestion
         */
-       public function testRewriteQueryWithSuggestion( $message, $expectRegex, 
$fromResults ) {
-               $mockSearchEngine = $this->mockSearchEngine( $fromResults );
+       public function testRewriteQueryWithSuggestion( $message, $expectRegex, 
$results ) {
+               $mockSearchEngine = $this->mockSearchEngine( $results );
                $search = $this->getMockBuilder( 'SpecialSearch' )
                        ->setMethods( array( 'getSearchEngine' ) )
                        ->getMock();
@@ -199,17 +190,14 @@
                }
        }
 
-       protected function mockSearchEngine( array $returnValues ) {
+       protected function mockSearchEngine( $results ) {
                $mock = $this->getMockBuilder( 'SearchEngine' )
-                       ->setMethods( array( 'searchText' ) )
+                       ->setMethods( array( 'searchText', 'searchTitle' ) )
                        ->getMock();
 
                $mock->expects( $this->any() )
                        ->method( 'searchText' )
-                       ->will( call_user_func_array(
-                               array( $this, 'onConsecutiveCalls' ),
-                               array_map( array( $this, 'returnValue' ), 
$returnValues )
-                       ) );
+                       ->will( $this->returnValue( $results ) );
 
                return $mock;
        }
@@ -219,9 +207,10 @@
        protected $results;
        protected $suggestion;
 
-       public function __construct( $suggestion = null, array $results = 
array(), $containedSyntax = false) {
-               $this->results = $results;
+       public function __construct( $suggestion = null, $rewrittenQuery = 
null, array $results = array(), $containedSyntax = false) {
                $this->suggestion = $suggestion;
+               $this->rewrittenQuery = $rewrittenQuery;
+               $this->results = $results;
                $this->containedSyntax = $containedSyntax;
        }
 
@@ -244,4 +233,16 @@
        public function getSuggestionSnippet() {
                return $this->suggestion;
        }
+
+       public function hasRewrittenQuery() {
+               return $this->rewrittenQuery !== null;
+       }
+
+       public function getQueryAfterRewrite() {
+               return $this->rewrittenQuery;
+       }
+
+       public function getQueryAfterRewriteSnippet() {
+               return htmlspecialchars( $this->rewrittenQuery );
+       }
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/227501
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0a8f75759f9148f53358707369b8a7128215de86
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: EBernhardson <ebernhard...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to