Manybubbles has uploaded a new change for review.

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


Change subject: Switch to elasticsearch.
......................................................................

Switch to elasticsearch.

Change-Id: Iaf05d67cac7c4a61158a54c3c03f30bbc35b1cec
---
A .gitmodules
M CirrusSearch.body.php
M CirrusSearch.php
M CirrusSearchUpdater.php
A Elastica
D buildSolrConfig.php
A updateElasticsearchIndex.php
7 files changed, 245 insertions(+), 199 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/CirrusSearch 
refs/changes/56/72956/1

diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..952bdae
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "Elastica"]
+       path = Elastica
+       url = https://github.com/ruflin/Elastica.git
diff --git a/CirrusSearch.body.php b/CirrusSearch.body.php
index 64c3d3c..a6558fa 100644
--- a/CirrusSearch.body.php
+++ b/CirrusSearch.body.php
@@ -21,71 +21,68 @@
        /**
         * Singleton instance of the client
         *
-        * @var Solarium_Client
+        * @var \Elastica\Index
         */
-       private static $client = null;
+       private static $index = null;
 
        /**
-        * Fetch the Solr client.
+        * Fetch the Elastica Index.
         *
-        * @return Solarium_Client
+        * @return \Elastica\Index
         */
-       static function getClient() {
-               if ( self::$client != null ) {
-                       return self::$client;
+       public static function getIndex() {
+               if ( self::$index != null ) {
+                       return self::$index;
                }
                global $wgCirrusSearchServers, $wgCirrusSearchMaxRetries;
 
-               self::$client = new Solarium_Client();
-               self::$client->setAdapter( 'Solarium_Client_Adapter_Curl' );
-       
-               // Setup the load balancer
-               $loadBalancer = self::$client->getPlugin( 'loadbalancer' );
-
-               // Allow updates to be load balancer just like creates
-               $loadBalancer->clearBlockedQueryTypes();
-
-               // Setup failover
-               if ( $wgCirrusSearchMaxRetries > 1 ) { 
-                       $loadBalancer->setFailoverEnabled( true );
-                       $loadBalancer->setFailoverMaxRetries( 
$wgCirrusSearchMaxRetries );
-               }
-
-               // Setup the Solr endpoints
+               // Setup the Elastica endpoints
+               $servers = array();
                foreach ( $wgCirrusSearchServers as $server ) {
-                       $serverConfig = array( 
-                               'host' => $server,
-                               'core' => wfWikiId()
-                       );
-                       $loadBalancer->addServer( $server, $serverConfig, 1 );
+                       $servers[] = array('host' => $server);
                }
-               return self::$client;
+               $client = new \Elastica\Client( array(
+                       'servers' => $servers
+               ) );
+               self::$index = $client->getIndex( wfWikiId() );
+
+               return self::$index;
+       }
+
+       /**
+        * Fetch the Elastica Type for pages.
+        *
+        * @ \Elastica\Type
+        */
+       static function getPageType() {
+               return CirrusSearch::getIndex()->getType('page');
        }
 
        public static function prefixSearch( $ns, $search, $limit, &$results ) {
+               wfDebugLog( 'CirrusSearch', "Prefix searching:  $search" );
                // Boilerplate
                $nsNames = 
RequestContext::getMain()->getLanguage()->getNamespaces();
-               $client = self::getClient();
-               $query = $client->createSelect();
+               $query = new Elastica\Query();
+               $query->setFields( array( 'id', 'title', 'namespace' ) );
 
                // Query params
-               $query->setRows( $limit );
-               wfDebugLog( 'CirrusSearch', "Prefix searching:  $search" );
-               if( count( $ns ) ) {
-                       $query = self::setNamespaceFilter( $ns, $query );
-               }
-               $query->setQuery( 'titlePrefix:%T1%', array( $search  ) );
+               $query->setLimit( $limit );
+               $query->setFilter( CirrusSearch::buildNamespaceFilter( $ns ) );
+               // TODO remove the strtolower and let elasticsearch do it 
because it is a tokenizing beast
+               $query->setQuery( new \Elastica\Query\Prefix( array( 'title' => 
strtolower( $search ) ) ) );
 
                // Perform the search
                try {
-                       $res = $client->select( $query );
+                       $result = CirrusSearch::getPageType()->search( $query );
+                       wfDebugLog( 'CirrusSearch', 'Search completed in ' . 
$result->getTotalTime() . ' millis' );
                } catch ( Solarium_Exception $e ) {
+                       // TODO find the right exception
                        wfLogWarning( "Search backend error during title prefix 
search for '$search'." );
                        return false;
                }
 
                // We only care about title results
-               foreach( $res as $r ) {
+               foreach( $result->getResults() as $r ) {
                        $results[] = Title::makeTitle( $r->namespace, $r->title 
)->getPrefixedText();
                }
 
@@ -93,13 +90,9 @@
        }
 
        public function searchText( $term ) {
+               wfDebugLog( 'CirrusSearch', "Searching:  $term" );
+               
                $originalTerm = $term;
-               function addHighlighting( $highlighting, $term ) {
-                       if ( $highlighting->getQuery() !== null ) {
-                               $term = $highlighting->getQuery() . ' OR ' . 
$term;
-                       }
-                       $highlighting->setQuery( $term );
-               }
 
                // Ignore leading ~ because it is used to force displaying 
search results but not to effect them
                if ( substr( $term, 0, 1 ) === '~' )  {
@@ -107,45 +100,41 @@
                }
 
                // Boilerplate
-               $client = self::getClient();
-               $query = $client->createSelect();
+               $query = new Elastica\Query();
                $query->setFields( array( 'id', 'title', 'namespace' ) );
+
+               $filters = array();
 
                // Offset/limit
                if( $this->offset ) {
-                       $query->setStart( $this->offset );
+                       $query->setFrom( $this->offset );
                }
                if( $this->limit ) {
-                       $query->setRows( $this->limit );
+                       $query->setLimit( $this->limit );
                }
-
-               // Namespaces
-               $query = self::setNamespaceFilter( $this->namespaces, $query );
-
-               $dismax = $query->getDismax();
-               $dismax->setQueryParser( 'edismax' );
-               $dismax->setPhraseFields( 'title^1000.0 text^1000.0' );
-               $dismax->setPhraseSlop( '3' );
-               $dismax->setQueryFields( 'title^20.0 text^3.0' );
-
-               $highlighting = $query->getHighlighting();
+               $filters[] = CirrusSearch::buildNamespaceFilter( 
$this->namespaces );
 
                $term = preg_replace_callback(
                        '/(?<key>[^ ]+):(?<value>(?:"[^"]+")|(?:[^ ]+)) ?/',
-                       function ( $matches ) use ( $query, $highlighting ) {
+                       function ( $matches ) use ( &$filters ) {
                                $key = $matches['key'];
                                $value = trim( $matches['value'], '"' );
                                switch ( $key ) {
                                        case 'incategory':
-                                               $query->createFilterQuery( 
"$key:$value" )->setQuery( '+category:%P1%', array( $value ) );
+                                               $filters[] = new 
\Elastica\Filter\Term( array( 'category' => $value ) );
+                                               // TODO I used to add 
highlighting here for $value
                                                return '';
                                        case 'prefix':
-                                               $query->createFilterQuery( 
"$key:$value" )->setQuery( '+titlePrefix:%P1% OR +textPrefix:%P1%', array( 
$value ) );
-                                               addHighlighting( $highlighting, 
"$value*" );
+                                               // TODO maybe we're better 
+                                               $filter = new 
\Elastica\Filter\BoolOr();
+                                               $filter->addFilter( new 
\Elastica\Filter\Prefix( 'title', $value ) );
+                                               $filter->addFilter( new 
\Elastica\Filter\Prefix( 'text', $value ) );
+                                               $filters[] = $filter;
+                                               // TODO I used to add 
highlighting here for $value*
                                                return '';
                                        case 'intitle':
-                                               $query->createFilterQuery( 
"$key:$value" )->setQuery( '+title:%P1%', array( $value ) );
-                                               addHighlighting( $highlighting, 
$value );
+                                               $filters[] = new 
\Elastica\Filter\Term( array( 'title' => $value ) );
+                                               // TODO I used to add 
highlighting here for $value
                                                return '';
                                        default:
                                                return $matches[0];
@@ -154,36 +143,42 @@
                        $term
                );
 
-               if ( $this->namespaces !== null ) {
-                       $query->createFilterQuery( 'namspaces' )->setQuery( 
'+namespace:(' . implode( ' OR ', $this->namespaces ) . ')' );
-               }
+               // TODO do I really not have to/get to specify the terms to try 
to highlight?
+               // This seems out of the style of the rest of the Elastica....
+               $query->setHighlight( array( 
+                       'pre_tags' => array( '<span class="searchmatch">' ),
+                       'post_tags' => array( '</span>' ),
+                       'fields' => array(
+                               'title' => array( 'number_of_fragments' => 0 ), 
// Don't fragment the title - it is too small.
+                               'text' => array( 'number_of_fragments' => 1 )
+                       )
+               ) );
 
-               /*
-                * Escape some special characters that we don't want users to 
pass to solr directly.
-                * These special characters _aren't_ escaped: * and ~
-                * *: Do a prefix or postfix search against the stemmed text 
which isn't strictly a good
-                * idea but this is so rarely used that adding extra code to 
flip prefix searches into
-                * real prefix searches isn't really worth it.  The same goes 
for postfix searches but
-                * doubly because we don't have a postfix index (backwards 
ngram.)
-                * ~: Do a fuzzy match against the stemmed text which isn't 
strictly a good idea but it
-                * gets the job done and fuzzy matches are a really rarely used 
feature to be creating an
-                * extra index for.
-                */
-               $term = preg_replace ( 
'/(\+|-|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|\?|:|\\\)/', '\\\$1', $term );
+               $filters = array_filter( $filters );
+               if ( count( $filters ) ) {
+                       $filter = new \Elastica\Filter\BoolAnd();
+                       $filter->setFilters( $filters );
+                       $query->setFilter( $filter );
+                       wfDebugLog( 'CirrusSearch', 'Setting up ' . count( 
$filters ) . ' filter' );
+               }
 
                // Actual text query
-               if ( trim( $term ) === '' ) {
-                       $term = '*:*';
-               } else {
-                       $spellCheck = $query->getSpellCheck()->setQuery( $term 
);
-                       addHighlighting( $highlighting, $term );
+               if ( trim( $term ) !== '' ) {
+                       // TODO make sure the query is well formed or make 
elasticsearch do it.
+                       $queryStringQuery = new \Elastica\Query\QueryString( 
$term );
+                       $queryStringQuery->setFields( array( 'title^20.0', 
'text^3.0' ) );
+                       $queryStringQuery->setAutoGeneratePhraseQueries( true );
+                       $queryStringQuery->setPhraseSlop( 3 );
+                       // TODO phrase match boosts?
+                       $query->setQuery( $queryStringQuery );
+                       // TODO spellcheck
                }
-               wfDebugLog( 'CirrusSearch', "Searching:  $term" );
-               $query->setQuery( $term );
 
                // Perform the search and return a result set
                try {
-                       return new CirrusSearchResultSet( $client->select( 
$query ) );
+                       $result = CirrusSearch::getPageType()->search( $query );
+                       wfDebugLog( 'CirrusSearch', 'Search completed in ' . 
$result->getTotalTime() . ' millis' );
+                       return new CirrusSearchResultSet( $result );
                } catch ( Solarium_Exception $e ) {
                        $status = new Status();
                        $status->warning( 'cirrussearch-backend-error' );
@@ -196,13 +191,12 @@
         * Filter a query to only return results in given namespace(s)
         *
         * @param array $ns Array of namespaces
-        * @param Solarium_Query $query
-        * @return Solarium_Query
         */
-       private static function setNamespaceFilter( array $ns, $query ) {
-               $query->createFilterQuery( 'namespace' )
-                               ->setQuery( 'namespace:' . implode( ' OR ', $ns 
) );
-               return $query;
+       private static function buildNamespaceFilter( array $ns ) {
+               if ( $ns !== null && count( $ns ) ) {
+                       return new \Elastica\Filter\Terms( 'namespace', $ns );
+               }
+               return null;
        }
 
        public function update( $id, $title, $text ) {
@@ -247,30 +241,29 @@
 
        public function __construct( $res ) {
                $this->result = $res;
-               $this->docs = $res->getDocuments();
                $this->hits = $res->count();
-               $this->totalHits = $res->getNumFound();
-               $spellcheck = $res->getSpellcheck();
+               $this->totalHits = $res->getTotalHits();
+               // $spellcheck = $res->getSpellcheck();
                $this->suggestionQuery = null;
                $this->suggestionSnippet = null;
-               if ( $spellcheck !== null && 
!$spellcheck->getCorrectlySpelled()  ) {
-                       $collation = $spellcheck->getCollation();
-                       if ( $collation !== null ) {
-                               $this->suggestionQuery = $collation->getQuery();
-                               $keys = array();
-                               $highlightedKeys = array();
-                               foreach ( $collation->getCorrections() as 
$misspelling => $correction ) {
-                                       // Oddly Solr will sometimes claim that 
a word is misspelled and then not provide a better spelling for it.
-                                       if ( $misspelling === $correction ) {
-                                               continue;
-                                       }
-                                       // TODO escaping danger
-                                       $keys[] = "/$correction/";
-                                       $highlightedKeys[] = 
"<em>$correction</em>";
-                               }
-                               $this->suggestionSnippet = preg_replace( $keys, 
$highlightedKeys, $this->suggestionQuery );
-                       }
-               }
+               // if ( $spellcheck !== null && 
!$spellcheck->getCorrectlySpelled()  ) {
+               //      $collation = $spellcheck->getCollation();
+               //      if ( $collation !== null ) {
+               //              $this->suggestionQuery = $collation->getQuery();
+               //              $keys = array();
+               //              $highlightedKeys = array();
+               //              foreach ( $collation->getCorrections() as 
$misspelling => $correction ) {
+               //                      // Oddly Solr will sometimes claim that 
a word is misspelled and then not provide a better spelling for it.
+               //                      if ( $misspelling === $correction ) {
+               //                              continue;
+               //                      }
+               //                      // TODO escaping danger
+               //                      $keys[] = "/$correction/";
+               //                      $highlightedKeys[] = 
"<em>$correction</em>";
+               //              }
+               //              $this->suggestionSnippet = preg_replace( $keys, 
$highlightedKeys, $this->suggestionQuery );
+               //      }
+               // }
        }
 
        public function hasResults() {
@@ -298,13 +291,12 @@
        }
 
        public function next() {
-               static $pos = 0;
-               $solrResult = null;
-               if( isset( $this->docs[$pos] ) ) {
-                       $solrResult = new CirrusSearchResult( $this->result, 
$this->docs[$pos] );
-                       $pos++;
+               $current = $this->result->current();
+               if ( $current ) {
+                       $this->result->next();
+                       return new CirrusSearchResult( $current );      
                }
-               return $solrResult;
+               return false;
        }
 }
 
@@ -314,19 +306,17 @@
 class CirrusSearchResult extends SearchResult {
        private $titleSnippet, $textSnippet;
 
-       public function __construct( $result, $doc ) {
-               $fields = $doc->getFields();
-               $highlighting = $result->getHighlighting()->getResult( $fields[ 
'id' ] )->getFields();
-
-               $this->initFromTitle( Title::makeTitle( $fields['namespace'], 
$fields[ 'title' ] ) );
-               if ( isset( $highlighting[ 'title' ] ) ) {
+       public function __construct( $result ) {
+               $this->initFromTitle( Title::makeTitle( $result->namespace, 
$result->title ) );
+               $highlights = $result->getHighlights();
+               if ( isset( $highlights[ 'title' ] ) ) {
                        // @todo: This should also show the namespace, we know 
it
-                       $this->titleSnippet = $highlighting[ 'title' ][ 0 ];
+                       $this->titleSnippet = $highlights[ 'title' ][ 0 ];
                } else {
                        $this->titleSnippet = '';
                }
-               if ( isset( $highlighting[ 'text' ] ) ) {
-                       $this->textSnippet = $highlighting[ 'text' ][ 0 ];
+               if ( isset( $highlights[ 'text' ] ) ) {
+                       $this->textSnippet = $highlights[ 'text' ][ 0 ];
                } else {
                        list( $contextLines, $contextChars ) = 
SearchEngine::userHighlightPrefs();
                        $this->initText();
diff --git a/CirrusSearch.php b/CirrusSearch.php
index df78ecd..8975cb3 100644
--- a/CirrusSearch.php
+++ b/CirrusSearch.php
@@ -37,7 +37,10 @@
  */
 
 // Solr servers
-$wgCirrusSearchServers = array( 'solr1', 'solr2', 'solr3', 'solr4' );
+$wgCirrusSearchServers = array( 'elasticsearch1', 'elasticsearch2', 
'elasticsearch3', 'elasticsearch4' );
+
+// Number of shards
+$wgCirrusSearchShardCount = 64;
 
 // Maximum times to retry on failure
 $wgCirrusSearchMaxRetries = 3;
@@ -82,6 +85,7 @@
 $wgCirrusSearchDocumentCacheSize = 16 * 1024;
 
 $dir = __DIR__ . '/';
+$elasticaDir = $dir . 'Elastica/lib/Elastica/';
 /**
  * Classes
  */
@@ -91,6 +95,44 @@
 $wgAutoloadClasses['SchemaBuilder'] = $dir . 'config/SchemaBuilder.php';
 $wgAutoloadClasses['SolrConfigBuilder'] = $dir . 
'config/SolrConfigBuilder.php';
 $wgAutoloadClasses['TypesBuilder'] = $dir . 'config/TypesBuilder.php';
+$wgAutoloadClasses['Elastica\Bulk'] = $elasticaDir . 'Bulk.php';
+$wgAutoloadClasses['Elastica\Client'] = $elasticaDir . 'Client.php';
+$wgAutoloadClasses['Elastica\Connection'] = $elasticaDir . 'Connection.php';
+$wgAutoloadClasses['Elastica\Document'] = $elasticaDir . 'Document.php';
+$wgAutoloadClasses['Elastica\Index'] = $elasticaDir . 'Index.php';
+$wgAutoloadClasses['Elastica\Param'] = $elasticaDir . 'Param.php';
+$wgAutoloadClasses['Elastica\Query'] = $elasticaDir . 'Query.php';
+$wgAutoloadClasses['Elastica\Request'] = $elasticaDir . 'Request.php';
+$wgAutoloadClasses['Elastica\Response'] = $elasticaDir . 'Response.php';
+$wgAutoloadClasses['Elastica\Result'] = $elasticaDir . 'Result.php';
+$wgAutoloadClasses['Elastica\ResultSet'] = $elasticaDir . 'ResultSet.php';
+$wgAutoloadClasses['Elastica\Search'] = $elasticaDir . 'Search.php';
+$wgAutoloadClasses['Elastica\SearchableInterface'] = $elasticaDir . 
'SearchableInterface.php';
+$wgAutoloadClasses['Elastica\Type'] = $elasticaDir . 'Type.php';
+$wgAutoloadClasses['Elastica\Util'] = $elasticaDir . 'Util.php';
+$wgAutoloadClasses['Elastica\Bulk\Action'] = $elasticaDir . 'Bulk/Action.php';
+$wgAutoloadClasses['Elastica\Bulk\Action\AbstractDocument'] = $elasticaDir . 
'Bulk/Action/AbstractDocument.php';
+$wgAutoloadClasses['Elastica\Bulk\Action\IndexDocument'] = $elasticaDir . 
'Bulk/Action/IndexDocument.php';
+$wgAutoloadClasses['Elastica\Bulk\Response'] = $elasticaDir . 
'Bulk/Response.php';
+$wgAutoloadClasses['Elastica\Bulk\ResponseSet'] = $elasticaDir . 
'Bulk/ResponseSet.php';
+$wgAutoloadClasses['Elastica\Exception\ExceptionInterface'] = $elasticaDir . 
'Exception/ExceptionInterface.php';
+$wgAutoloadClasses['Elastica\Exception\InvalidException'] = $elasticaDir . 
'Exception/InvalidException.php';
+$wgAutoloadClasses['Elastica\Exception\ResponseException'] = $elasticaDir . 
'Exception/ResponseException.php';
+$wgAutoloadClasses['Elastica\Filter\AbstractFilter'] = $elasticaDir . 
'Filter/AbstractFilter.php';
+$wgAutoloadClasses['Elastica\Filter\AbstractMulti'] = $elasticaDir . 
'Filter/AbstractMulti.php';
+$wgAutoloadClasses['Elastica\Filter\BoolAnd'] = $elasticaDir . 
'Filter/BoolAnd.php';
+$wgAutoloadClasses['Elastica\Filter\BoolOr'] = $elasticaDir . 
'Filter/BoolOr.php';
+$wgAutoloadClasses['Elastica\Filter\Prefix'] = $elasticaDir . 
'Filter/Prefix.php';
+$wgAutoloadClasses['Elastica\Filter\Term'] = $elasticaDir . 'Filter/Term.php';
+$wgAutoloadClasses['Elastica\Filter\Terms'] = $elasticaDir . 
'Filter/Terms.php';
+$wgAutoloadClasses['Elastica\Query\AbstractQuery'] = $elasticaDir . 
'Query/AbstractQuery.php';
+$wgAutoloadClasses['Elastica\Query\MatchAll'] = $elasticaDir . 
'Query/MatchAll.php';
+$wgAutoloadClasses['Elastica\Query\Prefix'] = $elasticaDir . 
'Query/Prefix.php';
+$wgAutoloadClasses['Elastica\Query\QueryString'] = $elasticaDir . 
'Query/QueryString.php';
+$wgAutoloadClasses['Elastica\Transport\AbstractTransport'] = $elasticaDir . 
'Transport/AbstractTransport.php';
+$wgAutoloadClasses['Elastica\Transport\Http'] = $elasticaDir . 
'Transport/Http.php';
+
+
 
 /**
  * Hooks
diff --git a/CirrusSearchUpdater.php b/CirrusSearchUpdater.php
index fcdb7cc..54290ab 100644
--- a/CirrusSearchUpdater.php
+++ b/CirrusSearchUpdater.php
@@ -28,23 +28,22 @@
        public static function updateRevisions( $pageData ) {
                wfProfileIn( __METHOD__ );
 
-               $client = CirrusSearch::getClient();
-               $host = $client->getAdapter()->getHost();
+               $documents = array();
+               foreach ( $pageData as $page ) {
+                       // @todo When $text is null, we only want to update the 
title, not the whole document
+                       $documents[] = 
CirrusSearchUpdater::buildDocumentforRevision( $page['rev'], $page['text'] );
+               }
+
                $method = __METHOD__;
-               $work = new PoolCounterWorkViaCallback( 'CirrusSearch-Update', 
"_solr:host:$host",
-                       array( 'doWork' => function() use ( $client, $pageData, 
$method ) {
+               // TODO I think this needs more configuration somewhere
+               $work = new PoolCounterWorkViaCallback( 'CirrusSearch-Update', 
"_elasticsearch",
+                       array( 'doWork' => function() use ( $documents, $method 
) {
                                wfProfileIn( $method . '::doWork' );
-                               $update = $client->createUpdate();
-                               foreach ( $pageData as $page ) {
-                                       // @todo When $text is null, we only 
want to update the title, not the whole document
-                                       $update->addDocument( 
CirrusSearchUpdater::buildDocumentforRevision( $page['rev'], $page['text'] ) );
-                               }
                                try {
-                                       wfProfileIn( $method . 
'::doWork::sendToSolr' );
-                                       $result = $client->update( $update );
-                                       wfProfileOut( $method . 
'::doWork::sendToSolr' );
-                                       wfDebugLog( 'CirrusSearch', 'Update 
completed in ' . $result->getQueryTime() . ' millis and has status ' . 
$result->getStatus() );
-                               } catch ( Solarium_Exception $e ) {
+                                       $result = 
CirrusSearch::getPageType()->addDocuments( $documents );
+                                       wfDebugLog( 'CirrusSearch', 'Update 
completed in ' . $result->getEngineTime() . ' (engine) millis' );
+                               } catch ( 
\Elastica\Exception\Bulk\ResponseException $e ) {
+                                       // TODO verify this is the right 
exception
                                        error_log( "CirrusSearch update failed 
caused by:  " . $e->getMessage() );
                                }
                                wfProfileOut( $method . '::doWork' );
@@ -61,18 +60,21 @@
                $article = new Article( $title, $revision->getId() );
                $parserOutput = $article->getParserOutput( $revision->getId() );
 
-               $doc = new Solarium_Document_ReadWrite();
-               $doc->id = $revision->getPage();
-               $doc->namespace = $title->getNamespace();
-               $doc->title = $title->getText();
-               $doc->text = Sanitizer::stripAllTags( $text );
-               $doc->textLen = $revision->getSize();
-               $doc->timestamp = wfTimestamp( TS_ISO_8601, 
$revision->getTimestamp() );
                // TODO this seems aweful hacky
+               $categories = array();
                foreach ( $parserOutput->getCategories() as $key => $value ) {
-                       $doc->addField( 'category', $key );
+                       $categories[] = $key;
                }
 
+               $doc = new \Elastica\Document( $revision->getPage(), array(
+                       'namespace' => $title->getNamespace(),
+                       'title' => $title->getText(),
+                       'text' => Sanitizer::stripAllTags( $text ),
+                       'textLen' => $revision->getSize(),
+                       'timestamp' => wfTimestamp( TS_ISO_8601, 
$revision->getTimestamp() ),
+                       'category' => $categories
+               ));
+
                wfProfileOut( __METHOD__ );
                return $doc;
        }
diff --git a/Elastica b/Elastica
new file mode 160000
index 0000000..f0d77c4
--- /dev/null
+++ b/Elastica
+Subproject commit f0d77c44748717a27a87fa47f7003831220cab88
diff --git a/buildSolrConfig.php b/buildSolrConfig.php
deleted file mode 100644
index efa468d..0000000
--- a/buildSolrConfig.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-/**
- * Generate the Solr configuration
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- */
-require_once( "maintenance/Maintenance.php" );
-
-/**
- * Build a solr config directory.
- */
-class BuildSolrConfig extends Maintenance {
-       public function __construct() {
-               parent::__construct();
-               $this->mDescription = "Build a Solr config directory for this 
wiki";
-               $this->addOption( 'where', 'Defaults to /tmp/solrConfig/<pid>', 
false, true );
-       }
-       public function execute() {
-               $where = $this->getOption( 'where', '/tmp/solrConfig' . 
getmypid() );
-               if ( file_exists( $where ) ) {
-                       $this->error( "$where already exists so I can't build a 
new solr config there.", true );
-               }
-               $this->output( "Building solr config in $where\n" );
-               $schemaBuilder = new SchemaBuilder( $where );
-               $schemaBuilder->build();
-               $solrConfigBuilder = new SolrConfigBuilder( $where );
-               $solrConfigBuilder->build();
-       }
-}
-
-$maintClass = "BuildSolrConfig";
-require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/updateElasticsearchIndex.php b/updateElasticsearchIndex.php
new file mode 100644
index 0000000..a957714
--- /dev/null
+++ b/updateElasticsearchIndex.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Generate the Solr configuration
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+require_once( "maintenance/Maintenance.php" );
+
+/**
+ * Build a solr config directory.
+ */
+class UpdateElasticsearchIndex extends Maintenance {
+       public function __construct() {
+               parent::__construct();
+               $this->mDescription = "Update the elasticsearch index for this 
wiki";
+               $this->addOption( 'rebuild', 'Rebuild the index' );
+       }
+       public function execute() {
+               global $wgCirrusSearchShardCount, $wgCirrusSearchReplicatCount;
+               $rebuild = $this->getOption( 'rebuild', false );
+               if ( $rebuild ) {
+                       $this->output( "Rebuilding index\n" );
+                       $rebuild = true;
+               } else {
+                       $this->output( "Createing index\n" );
+                       // TODO update the index if it already exists/warn user 
about what can't be updated.
+               }
+               CirrusSearch::getIndex()->create( array(
+                       'number_of_shards' => $wgCirrusSearchShardCount,
+               'number_of_replicas' => $wgCirrusSearchReplicatCount
+               ), $rebuild );
+               // TODO build the analyzers and mappings
+               // $schemaBuilder = new SchemaBuilder( $where );
+               // $schemaBuilder->build();
+               // $solrConfigBuilder = new SolrConfigBuilder( $where );
+               // $solrConfigBuilder->build();
+       }
+}
+
+$maintClass = "UpdateElasticsearchIndex";
+require_once RUN_MAINTENANCE_IF_MAIN;

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iaf05d67cac7c4a61158a54c3c03f30bbc35b1cec
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/CirrusSearch
Gerrit-Branch: master
Gerrit-Owner: Manybubbles <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to