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
