vendor/ongr/elasticsearch-dsl/src/Search.php line 223

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the ONGR package.
  4.  *
  5.  * (c) NFQ Technologies UAB <info@nfq.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace ONGR\ElasticsearchDSL;
  11. use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
  12. use ONGR\ElasticsearchDSL\Highlight\Highlight;
  13. use ONGR\ElasticsearchDSL\InnerHit\NestedInnerHit;
  14. use ONGR\ElasticsearchDSL\Query\Compound\BoolQuery;
  15. use ONGR\ElasticsearchDSL\SearchEndpoint\AbstractSearchEndpoint;
  16. use ONGR\ElasticsearchDSL\SearchEndpoint\AggregationsEndpoint;
  17. use ONGR\ElasticsearchDSL\SearchEndpoint\HighlightEndpoint;
  18. use ONGR\ElasticsearchDSL\SearchEndpoint\InnerHitsEndpoint;
  19. use ONGR\ElasticsearchDSL\SearchEndpoint\PostFilterEndpoint;
  20. use ONGR\ElasticsearchDSL\SearchEndpoint\QueryEndpoint;
  21. use ONGR\ElasticsearchDSL\SearchEndpoint\SearchEndpointFactory;
  22. use ONGR\ElasticsearchDSL\SearchEndpoint\SearchEndpointInterface;
  23. use ONGR\ElasticsearchDSL\SearchEndpoint\SortEndpoint;
  24. use ONGR\ElasticsearchDSL\Serializer\Normalizer\CustomReferencedNormalizer;
  25. use ONGR\ElasticsearchDSL\Serializer\OrderedSerializer;
  26. use Symfony\Component\Serializer\Normalizer\CustomNormalizer;
  27. use ONGR\ElasticsearchDSL\SearchEndpoint\SuggestEndpoint;
  28. /**
  29.  * Search object that can be executed by a manager.
  30.  */
  31. class Search
  32. {
  33.     /**
  34.      * If you don’t need to track the total number of hits at all you can improve
  35.      * query times by setting this option to false. Defaults to true.
  36.      *
  37.      * @var bool
  38.      */
  39.     private $trackTotalHits;
  40.     /**
  41.      * To retrieve hits from a certain offset. Defaults to 0.
  42.      *
  43.      * @var int
  44.      */
  45.     private $from;
  46.     /**
  47.      * The number of hits to return. Defaults to 10. If you do not care about getting some
  48.      * hits back but only about the number of matches and/or aggregations, setting the value
  49.      * to 0 will help performance.
  50.      *
  51.      * @var int
  52.      */
  53.     private $size;
  54.     /**
  55.      * Allows to control how the _source field is returned with every hit. By default
  56.      * operations return the contents of the _source field unless you have used the
  57.      * stored_fields parameter or if the _source field is disabled.
  58.      *
  59.      * @var bool
  60.      */
  61.     private $source;
  62.     /**
  63.      * Allows to selectively load specific stored fields for each document represented by a search hit.
  64.      *
  65.      * @var array
  66.      */
  67.     private $storedFields;
  68.     /**
  69.      * Allows to return a script evaluation (based on different fields) for each hit.
  70.      * Script fields can work on fields that are not stored, and allow to return custom
  71.      * values to be returned (the evaluated value of the script). Script fields can
  72.      * also access the actual _source document indexed and extract specific elements
  73.      * to be returned from it (can be an "object" type).
  74.      *
  75.      * @var array
  76.      */
  77.     private $scriptFields;
  78.     /**
  79.      * Allows to return the doc value representation of a field for each hit. Doc value
  80.      * fields can work on fields that are not stored. Note that if the fields parameter
  81.      * specifies fields without docvalues it will try to load the value from the fielddata
  82.      * cache causing the terms for that field to be loaded to memory (cached), which will
  83.      * result in more memory consumption.
  84.      *
  85.      * @var array
  86.      */
  87.     private $docValueFields;
  88.     /**
  89.      * Enables explanation for each hit on how its score was computed.
  90.      *
  91.      * @var bool
  92.      */
  93.     private $explain;
  94.     /**
  95.      * Returns a version for each search hit.
  96.      *
  97.      * @var bool
  98.      */
  99.     private $version;
  100.     /**
  101.      * Allows to configure different boost level per index when searching across more
  102.      * than one indices. This is very handy when hits coming from one index matter more
  103.      * than hits coming from another index (think social graph where each user has an index).
  104.      *
  105.      * @var array
  106.      */
  107.     private $indicesBoost;
  108.     /**
  109.      * Exclude documents which have a _score less than the minimum specified in min_score.
  110.      *
  111.      * @var int
  112.      */
  113.     private $minScore;
  114.     /**
  115.      * Pagination of results can be done by using the from and size but the cost becomes
  116.      * prohibitive when the deep pagination is reached. The index.max_result_window which
  117.      * defaults to 10,000 is a safeguard, search requests take heap memory and time
  118.      * proportional to from + size. The Scroll api is recommended for efficient deep
  119.      * scrolling but scroll contexts are costly and it is not recommended to use it for
  120.      * real time user requests. The search_after parameter circumvents this problem by
  121.      * providing a live cursor. The idea is to use the results from the previous page to
  122.      * help the retrieval of the next page.
  123.      *
  124.      * @var array
  125.      */
  126.     private $searchAfter;
  127.     /**
  128.      * URI parameters alongside Request body search.
  129.      *
  130.      * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html
  131.      *
  132.      * @var array
  133.      */
  134.     private $uriParams = [];
  135.     /**
  136.      * While a search request returns a single “page” of results, the scroll API can be used to retrieve
  137.      * large numbers of results (or even all results) from a single search request, in much the same way
  138.      * as you would use a cursor on a traditional database. Scrolling is not intended for real time user
  139.      * requests, but rather for processing large amounts of data, e.g. in order to reindex the contents
  140.      * of one index into a new index with a different configuration.
  141.      *
  142.      * @var string
  143.      */
  144.     private $scroll;
  145.     /**
  146.      * @var OrderedSerializer
  147.      */
  148.     private static $serializer;
  149.     /**
  150.      * @var SearchEndpointInterface[]
  151.      */
  152.     private $endpoints = [];
  153.     /**
  154.      * Constructor to initialize static properties
  155.      */
  156.     public function __construct()
  157.     {
  158.         $this->initializeSerializer();
  159.     }
  160.     /**
  161.      * Wakeup method to initialize static properties
  162.      */
  163.     public function __wakeup()
  164.     {
  165.         $this->initializeSerializer();
  166.     }
  167.     /**
  168.      * Initializes the serializer
  169.      */
  170.     private function initializeSerializer()
  171.     {
  172.         if (static::$serializer === null) {
  173.             static::$serializer = new OrderedSerializer(
  174.                 [
  175.                     new CustomReferencedNormalizer(),
  176.                     new CustomNormalizer(),
  177.                 ]
  178.             );
  179.         }
  180.     }
  181.     /**
  182.      * Destroys search endpoint.
  183.      *
  184.      * @param string $type Endpoint type.
  185.      */
  186.     public function destroyEndpoint($type)
  187.     {
  188.         unset($this->endpoints[$type]);
  189.     }
  190.     /**
  191.      * Adds query to the search.
  192.      *
  193.      * @param BuilderInterface $query
  194.      * @param string           $boolType
  195.      * @param string           $key
  196.      *
  197.      * @return $this
  198.      */
  199.     public function addQuery(BuilderInterface $query$boolType BoolQuery::MUST$key null)
  200.     {
  201.         $endpoint $this->getEndpoint(QueryEndpoint::NAME);
  202.         $endpoint->addToBool($query$boolType$key);
  203.         return $this;
  204.     }
  205.     /**
  206.      * Returns endpoint instance.
  207.      *
  208.      * @param string $type Endpoint type.
  209.      *
  210.      * @return SearchEndpointInterface
  211.      */
  212.     private function getEndpoint($type)
  213.     {
  214.         if (!array_key_exists($type$this->endpoints)) {
  215.             $this->endpoints[$type] = SearchEndpointFactory::get($type);
  216.         }
  217.         return $this->endpoints[$type];
  218.     }
  219.     /**
  220.      * Returns queries inside BoolQuery instance.
  221.      *
  222.      * @return BoolQuery
  223.      */
  224.     public function getQueries()
  225.     {
  226.         $endpoint $this->getEndpoint(QueryEndpoint::NAME);
  227.         return $endpoint->getBool();
  228.     }
  229.     /**
  230.      * Sets query endpoint parameters.
  231.      *
  232.      * @param array $parameters
  233.      *
  234.      * @return $this
  235.      */
  236.     public function setQueryParameters(array $parameters)
  237.     {
  238.         $this->setEndpointParameters(QueryEndpoint::NAME$parameters);
  239.         return $this;
  240.     }
  241.     /**
  242.      * Sets parameters to the endpoint.
  243.      *
  244.      * @param string $endpointName
  245.      * @param array  $parameters
  246.      *
  247.      * @return $this
  248.      */
  249.     public function setEndpointParameters($endpointName, array $parameters)
  250.     {
  251.         /** @var AbstractSearchEndpoint $endpoint */
  252.         $endpoint $this->getEndpoint($endpointName);
  253.         $endpoint->setParameters($parameters);
  254.         return $this;
  255.     }
  256.     /**
  257.      * Adds a post filter to search.
  258.      *
  259.      * @param BuilderInterface $filter   Filter.
  260.      * @param string           $boolType Example boolType values:
  261.      *                                   - must
  262.      *                                   - must_not
  263.      *                                   - should.
  264.      * @param string           $key
  265.      *
  266.      * @return $this.
  267.      */
  268.     public function addPostFilter(BuilderInterface $filter$boolType BoolQuery::MUST$key null)
  269.     {
  270.         $this
  271.             ->getEndpoint(PostFilterEndpoint::NAME)
  272.             ->addToBool($filter$boolType$key);
  273.         return $this;
  274.     }
  275.     /**
  276.      * Returns queries inside BoolFilter instance.
  277.      *
  278.      * @return BoolQuery
  279.      */
  280.     public function getPostFilters()
  281.     {
  282.         $endpoint $this->getEndpoint(PostFilterEndpoint::NAME);
  283.         return $endpoint->getBool();
  284.     }
  285.     /**
  286.      * Sets post filter endpoint parameters.
  287.      *
  288.      * @param array $parameters
  289.      *
  290.      * @return $this
  291.      */
  292.     public function setPostFilterParameters(array $parameters)
  293.     {
  294.         $this->setEndpointParameters(PostFilterEndpoint::NAME$parameters);
  295.         return $this;
  296.     }
  297.     /**
  298.      * Adds aggregation into search.
  299.      *
  300.      * @param AbstractAggregation $aggregation
  301.      *
  302.      * @return $this
  303.      */
  304.     public function addAggregation(AbstractAggregation $aggregation)
  305.     {
  306.         $this->getEndpoint(AggregationsEndpoint::NAME)->add($aggregation$aggregation->getName());
  307.         return $this;
  308.     }
  309.     /**
  310.      * Returns all aggregations.
  311.      *
  312.      * @return BuilderInterface[]
  313.      */
  314.     public function getAggregations()
  315.     {
  316.         return $this->getEndpoint(AggregationsEndpoint::NAME)->getAll();
  317.     }
  318.     /**
  319.      * Adds inner hit into search.
  320.      *
  321.      * @param NestedInnerHit $innerHit
  322.      *
  323.      * @return $this
  324.      */
  325.     public function addInnerHit(NestedInnerHit $innerHit)
  326.     {
  327.         $this->getEndpoint(InnerHitsEndpoint::NAME)->add($innerHit$innerHit->getName());
  328.         return $this;
  329.     }
  330.     /**
  331.      * Returns all inner hits.
  332.      *
  333.      * @return BuilderInterface[]
  334.      */
  335.     public function getInnerHits()
  336.     {
  337.         return $this->getEndpoint(InnerHitsEndpoint::NAME)->getAll();
  338.     }
  339.     /**
  340.      * Adds sort to search.
  341.      *
  342.      * @param BuilderInterface $sort
  343.      *
  344.      * @return $this
  345.      */
  346.     public function addSort(BuilderInterface $sort)
  347.     {
  348.         $this->getEndpoint(SortEndpoint::NAME)->add($sort);
  349.         return $this;
  350.     }
  351.     /**
  352.      * Returns all set sorts.
  353.      *
  354.      * @return BuilderInterface[]
  355.      */
  356.     public function getSorts()
  357.     {
  358.         return $this->getEndpoint(SortEndpoint::NAME)->getAll();
  359.     }
  360.     /**
  361.      * Allows to highlight search results on one or more fields.
  362.      *
  363.      * @param Highlight $highlight
  364.      *
  365.      * @return $this.
  366.      */
  367.     public function addHighlight($highlight)
  368.     {
  369.         $this->getEndpoint(HighlightEndpoint::NAME)->add($highlight);
  370.         return $this;
  371.     }
  372.     /**
  373.      * Returns highlight builder.
  374.      *
  375.      * @return BuilderInterface
  376.      */
  377.     public function getHighlights()
  378.     {
  379.         /** @var HighlightEndpoint $highlightEndpoint */
  380.         $highlightEndpoint $this->getEndpoint(HighlightEndpoint::NAME);
  381.         return $highlightEndpoint->getHighlight();
  382.     }
  383.     /**
  384.     * Adds suggest into search.
  385.     *
  386.     * @param BuilderInterface $suggest
  387.     *
  388.     * @return $this
  389.     */
  390.     public function addSuggest(NamedBuilderInterface $suggest)
  391.     {
  392.         $this->getEndpoint(SuggestEndpoint::NAME)->add($suggest$suggest->getName());
  393.         return $this;
  394.     }
  395.     /**
  396.     * Returns all suggests.
  397.     *
  398.     * @return BuilderInterface[]
  399.     */
  400.     public function getSuggests()
  401.     {
  402.         return $this->getEndpoint(SuggestEndpoint::NAME)->getAll();
  403.     }
  404.     /**
  405.      * @return null|int
  406.      */
  407.     public function getFrom()
  408.     {
  409.         return $this->from;
  410.     }
  411.     /**
  412.      * @param null|int $from
  413.      *
  414.      * @return $this
  415.      */
  416.     public function setFrom($from)
  417.     {
  418.         $this->from $from;
  419.         return $this;
  420.     }
  421.     /**
  422.      * @return bool
  423.      */
  424.     public function isTrackTotalHits()
  425.     {
  426.         return $this->trackTotalHits;
  427.     }
  428.     /**
  429.      * @param bool $trackTotalHits
  430.      *
  431.      * @return $this
  432.      */
  433.     public function setTrackTotalHits(bool $trackTotalHits)
  434.     {
  435.         $this->trackTotalHits $trackTotalHits;
  436.         return $this;
  437.     }
  438.     /**
  439.      * @return null|int
  440.      */
  441.     public function getSize()
  442.     {
  443.         return $this->size;
  444.     }
  445.     /**
  446.      * @param null|int $size
  447.      *
  448.      * @return $this
  449.      */
  450.     public function setSize($size)
  451.     {
  452.         $this->size $size;
  453.         return $this;
  454.     }
  455.     /**
  456.      * @return bool
  457.      */
  458.     public function isSource()
  459.     {
  460.         return $this->source;
  461.     }
  462.     /**
  463.      * @param bool $source
  464.      *
  465.      * @return $this
  466.      */
  467.     public function setSource($source)
  468.     {
  469.         $this->source $source;
  470.         return $this;
  471.     }
  472.     /**
  473.      * @return array
  474.      */
  475.     public function getStoredFields()
  476.     {
  477.         return $this->storedFields;
  478.     }
  479.     /**
  480.      * @param array $storedFields
  481.      *
  482.      * @return $this
  483.      */
  484.     public function setStoredFields($storedFields)
  485.     {
  486.         $this->storedFields $storedFields;
  487.         return $this;
  488.     }
  489.     /**
  490.      * @return array
  491.      */
  492.     public function getScriptFields()
  493.     {
  494.         return $this->scriptFields;
  495.     }
  496.     /**
  497.      * @param array $scriptFields
  498.      *
  499.      * @return $this
  500.      */
  501.     public function setScriptFields($scriptFields)
  502.     {
  503.         $this->scriptFields $scriptFields;
  504.         return $this;
  505.     }
  506.     /**
  507.      * @return array
  508.      */
  509.     public function getDocValueFields()
  510.     {
  511.         return $this->docValueFields;
  512.     }
  513.     /**
  514.      * @param array $docValueFields
  515.      *
  516.      * @return $this
  517.      */
  518.     public function setDocValueFields($docValueFields)
  519.     {
  520.         $this->docValueFields $docValueFields;
  521.         return $this;
  522.     }
  523.     /**
  524.      * @return bool
  525.      */
  526.     public function isExplain()
  527.     {
  528.         return $this->explain;
  529.     }
  530.     /**
  531.      * @param bool $explain
  532.      *
  533.      * @return $this
  534.      */
  535.     public function setExplain($explain)
  536.     {
  537.         $this->explain $explain;
  538.         return $this;
  539.     }
  540.     /**
  541.      * @return bool
  542.      */
  543.     public function isVersion()
  544.     {
  545.         return $this->version;
  546.     }
  547.     /**
  548.      * @param bool $version
  549.      *
  550.      * @return $this
  551.      */
  552.     public function setVersion($version)
  553.     {
  554.         $this->version $version;
  555.         return $this;
  556.     }
  557.     /**
  558.      * @return array
  559.      */
  560.     public function getIndicesBoost()
  561.     {
  562.         return $this->indicesBoost;
  563.     }
  564.     /**
  565.      * @param array $indicesBoost
  566.      *
  567.      * @return $this
  568.      */
  569.     public function setIndicesBoost($indicesBoost)
  570.     {
  571.         $this->indicesBoost $indicesBoost;
  572.         return $this;
  573.     }
  574.     /**
  575.      * @return int
  576.      */
  577.     public function getMinScore()
  578.     {
  579.         return $this->minScore;
  580.     }
  581.     /**
  582.      * @param int $minScore
  583.      *
  584.      * @return $this
  585.      */
  586.     public function setMinScore($minScore)
  587.     {
  588.         $this->minScore $minScore;
  589.         return $this;
  590.     }
  591.     /**
  592.      * @return array
  593.      */
  594.     public function getSearchAfter()
  595.     {
  596.         return $this->searchAfter;
  597.     }
  598.     /**
  599.      * @param array $searchAfter
  600.      *
  601.      * @return $this
  602.      */
  603.     public function setSearchAfter($searchAfter)
  604.     {
  605.         $this->searchAfter $searchAfter;
  606.         return $this;
  607.     }
  608.     /**
  609.      * @return string
  610.      */
  611.     public function getScroll()
  612.     {
  613.         return $this->scroll;
  614.     }
  615.     /**
  616.      * @param string $scroll
  617.      *
  618.      * @return $this
  619.      */
  620.     public function setScroll($scroll '5m')
  621.     {
  622.         $this->scroll $scroll;
  623.         $this->addUriParam('scroll'$this->scroll);
  624.         return $this;
  625.     }
  626.     /**
  627.      * @param string $name
  628.      * @param string|array|bool $value
  629.      *
  630.      * @return $this
  631.      */
  632.     public function addUriParam($name$value)
  633.     {
  634.         if (in_array($name, [
  635.             'q',
  636.             'df',
  637.             'analyzer',
  638.             'analyze_wildcard',
  639.             'default_operator',
  640.             'lenient',
  641.             'explain',
  642.             '_source',
  643.             '_source_exclude',
  644.             '_source_include',
  645.             'stored_fields',
  646.             'sort',
  647.             'track_scores',
  648.             'timeout',
  649.             'terminate_after',
  650.             'from',
  651.             'size',
  652.             'search_type',
  653.             'scroll',
  654.             'allow_no_indices',
  655.             'ignore_unavailable',
  656.             'typed_keys',
  657.             'pre_filter_shard_size',
  658.             'ignore_unavailable',
  659.         ])) {
  660.             $this->uriParams[$name] = $value;
  661.         } else {
  662.             throw new \InvalidArgumentException(sprintf('Parameter %s is not supported.'$value));
  663.         }
  664.         return $this;
  665.     }
  666.     /**
  667.      * Returns query url parameters.
  668.      *
  669.      * @return array
  670.      */
  671.     public function getUriParams()
  672.     {
  673.         return $this->uriParams;
  674.     }
  675.     /**
  676.      * {@inheritdoc}
  677.      */
  678.     public function toArray()
  679.     {
  680.         $output array_filter(static::$serializer->normalize($this->endpoints));
  681.         $params = [
  682.             'from' => 'from',
  683.             'size' => 'size',
  684.             'source' => '_source',
  685.             'storedFields' => 'stored_fields',
  686.             'scriptFields' => 'script_fields',
  687.             'docValueFields' => 'docvalue_fields',
  688.             'explain' => 'explain',
  689.             'version' => 'version',
  690.             'indicesBoost' => 'indices_boost',
  691.             'minScore' => 'min_score',
  692.             'searchAfter' => 'search_after',
  693.             'trackTotalHits' => 'track_total_hits',
  694.         ];
  695.         foreach ($params as $field => $param) {
  696.             if ($this->$field !== null) {
  697.                 $output[$param] = $this->$field;
  698.             }
  699.         }
  700.         return $output;
  701.     }
  702. }