Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
SatuFunctionScoreBuilder
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 3
72
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
42
 append
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getScript
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace CirrusSearch\Search\Rescore;
4
5use CirrusSearch\SearchConfig;
6use Elastica\Query\FunctionScore;
7
8/**
9 * Saturation function based on x/(k+x), k is a parameter
10 * to control how fast the function saturates.
11 * NOTE: that satu is always 0.5 when x == k.
12 * Parameter a is added to form a sigmoid : x^a/(k^a+x^a)
13 * Based on http://research.microsoft.com/pubs/65239/craswell_sigir05.pdf
14 * This function is suited to apply a new factor in a weighted sum.
15 */
16class SatuFunctionScoreBuilder extends FunctionScoreBuilder {
17    /** @var float */
18    private $k;
19    /** @var float */
20    private $a;
21    /** @var string */
22    private $field;
23
24    /**
25     * @param SearchConfig $config
26     * @param float $weight
27     * @param array $profile
28     * @throws InvalidRescoreProfileException
29     */
30    public function __construct( SearchConfig $config, $weight, $profile ) {
31        parent::__construct( $config, $weight );
32        if ( isset( $profile['k'] ) ) {
33            $this->k = $this->getOverriddenFactor( $profile['k'] );
34            if ( $this->k <= 0 ) {
35                throw new InvalidRescoreProfileException( 'Param k must be > 0' );
36            }
37        } else {
38            throw new InvalidRescoreProfileException( 'Param k is mandatory' );
39        }
40
41        if ( isset( $profile['a'] ) ) {
42            $this->a = $this->getOverriddenFactor( $profile['a'] );
43            if ( $this->a <= 0 ) {
44                throw new InvalidRescoreProfileException( 'Param a must be > 0' );
45            }
46        } else {
47            $this->a = 1;
48        }
49
50        if ( isset( $profile['field'] ) ) {
51            $this->field = $profile['field'];
52        } else {
53            throw new InvalidRescoreProfileException( 'Param field is mandatory' );
54        }
55    }
56
57    public function append( FunctionScore $functionScore ) {
58        $formula = $this->getScript();
59        $functionScore->addScriptScoreFunction( new \Elastica\Script\Script( $formula, null,
60            'expression' ), null, $this->weight );
61    }
62
63    /**
64     * @return string
65     */
66    public function getScript() {
67        $formula = "pow(doc['{$this->field}'].value , {$this->a}) / ";
68        $formula .= "( pow(doc['{$this->field}'].value, {$this->a}) + ";
69        $formula .= "pow({$this->k},{$this->a}))";
70
71        return $formula;
72    }
73}