Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 3 |
CRAP | |
0.00% |
0 / 53 |
FormSearchEntity | |
0.00% |
0 / 1 |
|
0.00% |
0 / 3 |
56 | |
0.00% |
0 / 53 |
getElasticSearchQuery | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 46 |
|||
makeResultType | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
|||
getRankedSearchResults | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
<?php | |
namespace Wikibase\Lexeme\Search\Elastic; | |
use CirrusSearch\Search\ResultsType; | |
use CirrusSearch\Search\SearchContext; | |
use Elastica\Query\AbstractQuery; | |
use Elastica\Query\BoolQuery; | |
use Elastica\Query\DisMax; | |
use Elastica\Query\MatchNone; | |
use Elastica\Query\MatchQuery; | |
use Elastica\Query\Term; | |
use Wikibase\Lexeme\MediaWiki\Content\LexemeContent; | |
use Wikibase\Search\Elastic\EntitySearchElastic; | |
use Wikibase\Search\Elastic\EntitySearchUtils; | |
/** | |
* Search for entity of type form. | |
* | |
* @license GPL-2.0-or-later | |
* @author Stas Malyshev | |
*/ | |
class FormSearchEntity extends LexemeSearchEntity { | |
/** | |
* Search limit. | |
* @var int | |
*/ | |
private $limit; | |
/** | |
* Produce ES query that matches the arguments. | |
* This is search for forms - matches only form representations | |
* but not lexemes. | |
* | |
* @param string $text | |
* @param string $entityType | |
* @param SearchContext $context | |
* | |
* @return AbstractQuery | |
*/ | |
protected function getElasticSearchQuery( | |
$text, | |
$entityType, | |
SearchContext $context | |
) { | |
$context->setOriginalSearchTerm( $text ); | |
// TODO consider using Form::ENTITY_TYPE | |
if ( $entityType !== 'form' ) { | |
$context->setResultsPossible( false ); | |
$context->addWarning( 'wikibase-search-bad-entity-type', $entityType ); | |
return new MatchNone(); | |
} | |
// Drop only leading spaces for exact matches, and all spaces for the rest | |
$textExact = ltrim( $text ); | |
$text = trim( $text ); | |
$labelsFilter = new MatchQuery( 'lexeme_forms.representation.prefix', $text ); | |
$profile = $context->getConfig() | |
->getProfileService() | |
->loadProfile( EntitySearchElastic::WIKIBASE_PREFIX_QUERY_BUILDER, | |
self::CONTEXT_LEXEME_PREFIX ); | |
$dismax = new DisMax(); | |
$dismax->setTieBreaker( 0 ); | |
$fields = [ | |
[ | |
"lexeme_forms.representation.near_match", | |
$profile['exact'] * $profile['form-discount'], | |
], | |
[ | |
"lexeme_forms.representation.near_match_folded", | |
$profile['folded'] * $profile['form-discount'], | |
], | |
]; | |
// Fields to which query applies exactly as stated, without trailing space trimming | |
$fieldsExact = []; | |
if ( $textExact !== $text ) { | |
$fields[] = | |
[ | |
"lexeme_forms.representation.prefix", | |
$profile['prefix'] * $profile['space-discount'] * $profile['form-discount'], | |
]; | |
$fieldsExact[] = | |
[ | |
"lexeme_forms.representation.prefix", | |
$profile['prefix'] * $profile['form-discount'], | |
]; | |
} else { | |
$fields[] = | |
[ | |
"lexeme_forms.representation.prefix", | |
$profile['prefix'] * $profile['form-discount'], | |
]; | |
} | |
foreach ( $fields as $field ) { | |
$dismax->addQuery( EntitySearchUtils::makeConstScoreQuery( $field[0], $field[1], | |
$text ) ); | |
} | |
foreach ( $fieldsExact as $field ) { | |
$dismax->addQuery( EntitySearchUtils::makeConstScoreQuery( $field[0], $field[1], | |
$textExact ) ); | |
} | |
$labelsQuery = new BoolQuery(); | |
$labelsQuery->addFilter( $labelsFilter ); | |
$labelsQuery->addShould( $dismax ); | |
// lexeme_forms.id is a lowercase_keyword so use Match to apply the analyzer | |
$titleMatch = new MatchQuery( 'lexeme_forms.id', | |
EntitySearchUtils::normalizeId( $text, $this->idParser ) ); | |
$query = new BoolQuery(); | |
// Match either labels or exact match to title | |
$query->addShould( $labelsQuery ); | |
$query->addShould( $titleMatch ); | |
$query->setMinimumShouldMatch( 1 ); | |
// Filter to fetch only given entity type | |
$query->addFilter( new Term( [ 'content_model' => LexemeContent::CONTENT_MODEL_ID ] ) ); | |
return $query; | |
} | |
/** | |
* Get results type object for this search. | |
* @return ResultsType | |
*/ | |
protected function makeResultType() { | |
return new FormTermResult( | |
$this->idParser, | |
$this->userLanguage, | |
$this->lookupFactory, | |
$this->limit | |
); | |
} | |
/** | |
* @inheritDoc | |
*/ | |
public function getRankedSearchResults( | |
$text, | |
$languageCode, | |
$entityType, | |
$limit, | |
$strictLanguage | |
) { | |
// We need to keep the limit since one document can produce several matches. | |
$this->limit = $limit; | |
return parent::getRankedSearchResults( $text, $languageCode, $entityType, $limit, | |
$strictLanguage ); | |
} | |
} |