/** * Get a random quip * * @return ResultSet */ public function getRandom() { $fs = new FunctionScore(); $fs->setRandomScore(); $query = new Query($fs); $query->setFrom(0)->setSize(1)->setFields($this->defaultFields()); return $this->doSearch($query); }
/** * @group functional * @expectedException \Elastica\Exception\InvalidException */ public function testArrayConfigSearch() { $client = $this->_getClient(); $search = new Search($client); $index = $client->getIndex('zero'); $index->create(array('index' => array('number_of_shards' => 1, 'number_of_replicas' => 0)), true); $docs = array(); for ($i = 0; $i < 11; ++$i) { $docs[] = new Document($i, array('id' => 1, 'email' => '*****@*****.**', 'username' => 'test')); } $type = $index->getType('zeroType'); $type->addDocuments($docs); $index->refresh(); $search->addIndex($index)->addType($type); //Backward compatibility, integer => limit // default limit results (default limit is 10) $resultSet = $search->search('test'); $this->assertEquals(10, $resultSet->count()); // limit = 1 $resultSet = $search->search('test', 1); $this->assertEquals(1, $resultSet->count()); //Array with limit $resultSet = $search->search('test', array('limit' => 2)); $this->assertEquals(2, $resultSet->count()); //Array with size $resultSet = $search->search('test', array('size' => 2)); $this->assertEquals(2, $resultSet->count()); //Array with from $resultSet = $search->search('test', array('from' => 10)); $this->assertEquals(10, $resultSet->current()->getId()); //Array with routing $resultSet = $search->search('test', array('routing' => 'r1,r2')); $this->assertEquals(10, $resultSet->count()); //Array with limit and routing $resultSet = $search->search('test', array('limit' => 5, 'routing' => 'r1,r2')); $this->assertEquals(5, $resultSet->count()); //Search types $resultSet = $search->search('test', array('limit' => 5, 'search_type' => 'count')); $this->assertTrue($resultSet->count() === 0 && $resultSet->getTotalHits() === 11); //Timeout - this one is a bit more tricky to test $mockResponse = new \Elastica\Response(json_encode(array('timed_out' => true))); $client = $this->getMockBuilder('Elastica\\Client')->disableOriginalConstructor()->getMock(); $client->method('request')->will($this->returnValue($mockResponse)); $search = new Search($client); $script = new Script('Thread.sleep(100); return _score;'); $query = new FunctionScore(); $query->addScriptScoreFunction($script); $resultSet = $search->search($query, array('timeout' => 50)); $this->assertTrue($resultSet->hasTimedOut()); // Throws InvalidException $resultSet = $search->search('test', array('invalid_option' => 'invalid_option_value')); }
/** * If there is any boosting to be done munge the the current query to get it right. */ private function installBoosts() { // Quick note: At the moment ".isEmpty()" is _much_ faster then ".empty". Never // use ".empty". See https://github.com/elasticsearch/elasticsearch/issues/5086 if ($this->sort !== 'relevance') { // Boosts are irrelevant if you aren't sorting by, well, relevance return; } $functionScore = new \Elastica\Query\FunctionScore(); $useFunctionScore = false; // Customize score by boosting based on incoming links count if ($this->boostLinks) { $useFunctionScore = true; if ($this->config->getElement('CirrusSearchWikimediaExtraPlugin', 'field_value_factor_with_default')) { $functionScore->addFunction('field_value_factor_with_default', array('field' => 'incoming_links', 'modifier' => 'log2p', 'missing' => 0)); } else { $scoreBoostExpression = "log10(doc['incoming_links'].value + 2)"; $functionScore->addScriptScoreFunction(new \Elastica\Script($scoreBoostExpression, null, 'expression')); } } // Customize score by decaying a portion by time since last update if ($this->preferRecentDecayPortion > 0 && $this->preferRecentHalfLife > 0) { // Convert half life for time in days to decay constant for time in milliseconds. $decayConstant = log(2) / $this->preferRecentHalfLife / 86400000; $parameters = array('decayConstant' => $decayConstant, 'decayPortion' => $this->preferRecentDecayPortion, 'nonDecayPortion' => 1 - $this->preferRecentDecayPortion, 'now' => time() * 1000); // e^ct where t is last modified time - now which is negative $exponentialDecayExpression = "exp(decayConstant * (doc['timestamp'].value - now))"; if ($this->preferRecentDecayPortion !== 1.0) { $exponentialDecayExpression = "{$exponentialDecayExpression} * decayPortion + nonDecayPortion"; } $functionScore->addScriptScoreFunction(new \Elastica\Script($exponentialDecayExpression, $parameters, 'expression')); $useFunctionScore = true; } // Add boosts for pages that contain certain templates if ($this->boostTemplates) { foreach ($this->boostTemplates as $name => $boost) { $match = new \Elastica\Query\Match(); $match->setFieldQuery('template', $name); $filterQuery = new \Elastica\Filter\Query($match); $filterQuery->setCached(true); $functionScore->addBoostFactorFunction($boost, $filterQuery); } $useFunctionScore = true; } // Add boosts for namespaces $namespacesToBoost = $this->namespaces ?: MWNamespace::getValidNamespaces(); if ($namespacesToBoost) { // Group common weights together and build a single filter per weight // to save on filters. $weightToNs = array(); foreach ($namespacesToBoost as $ns) { $weight = $this->getBoostForNamespace($ns); $weightToNs[(string) $weight][] = $ns; } if (count($weightToNs) > 1) { unset($weightToNs['1']); // That'd be redundant. foreach ($weightToNs as $weight => $namespaces) { $filter = new \Elastica\Filter\Terms('namespace', $namespaces); $functionScore->addBoostFactorFunction($weight, $filter); $useFunctionScore = true; } } } // Boost pages in a user's language $userLang = $this->config->getUserLanguage(); $userWeight = $this->config->getElement('CirrusSearchLanguageWeight', 'user'); if ($userWeight) { $functionScore->addBoostFactorFunction($userWeight, new \Elastica\Filter\Term(array('language' => $userLang))); $useFunctionScore = true; } // And a wiki's language, if it's different $wikiWeight = $this->config->getElement('CirrusSearchLanguageWeight', 'wiki'); if ($userLang != $this->config->get('LanguageCode') && $wikiWeight) { $functionScore->addBoostFactorFunction($wikiWeight, new \Elastica\Filter\Term(array('language' => $this->config->get('LanguageCode')))); $useFunctionScore = true; } if (!$useFunctionScore) { // Nothing to do return; } // The function score is done as a rescore on top of everything else $this->rescore[] = array('window_size' => $this->config->get('CirrusSearchFunctionRescoreWindowSize'), 'query' => array('rescore_query' => $functionScore, 'query_weight' => 1.0, 'rescore_query_weight' => 1.0, 'score_mode' => 'multiply')); }
/** * @group functional */ public function testFieldValueFactor() { $this->_checkVersion('1.6'); $expected = array('function_score' => array('functions' => array(array('field_value_factor' => array('field' => 'popularity', 'factor' => 1.2, 'modifier' => 'sqrt', 'missing' => 0.1))))); $query = new FunctionScore(); $query->addFieldValueFactorFunction('popularity', 1.2, FunctionScore::FIELD_VALUE_FACTOR_MODIFIER_SQRT, 0.1); $this->assertEquals($expected, $query->toArray()); $response = $this->_getIndexForTest()->search($query); $results = $response->getResults(); $this->assertCount(2, $results); $this->assertEquals(2, $results[0]->getId()); }
/** * @group functional */ public function testSetMinScore() { $expected = array('function_score' => array('min_score' => 0.8, 'functions' => array(array('gauss' => array('price' => array('origin' => 0, 'scale' => 10)))))); $query = new FunctionScore(); $query->addDecayFunction(FunctionScore::DECAY_GAUSS, 'price', 0, 10); $returnedValue = $query->setMinScore(0.8); $this->assertEquals($expected, $query->toArray()); $this->assertInstanceOf('Elastica\\Query\\FunctionScore', $returnedValue); $response = $this->_getIndexForTest()->search($query); $results = $response->getResults(); $this->assertCount(1, $results); $this->assertEquals(1, $results[0]->getId()); }
public function testScriptScore() { $scriptString = "_score * doc['price'].value"; $script = new Script($scriptString); $query = new FunctionScore(); $query->addScriptScoreFunction($script); $expected = array('function_score' => array('functions' => array(array('script_score' => array('script' => $scriptString))))); $this->assertEquals($expected, $query->toArray()); $response = $this->type->search($query); $results = $response->getResults(); // the document the highest price should be scored highest $result0 = $results[0]->getData(); $this->assertEquals("Miller's Field", $result0['name']); }
public function append(FunctionScore $functionScore) { $functionScore->addScriptScoreFunction(new \Elastica\Script($this->script, null, 'expression'), null, $this->weight); }