class SearchApiMultiQuery in Search API Multi-Index Searches 7
Standard implementation of SearchApiMultiQueryInterface.
If the search involves only a single server which supports the "search_api_multi" feature, the methods for this feature are used. Otherwise, generic code allows the searching of multiple indexes.
Hierarchy
- class \SearchApiMultiQuery implements SearchApiMultiQueryInterface
Expanded class hierarchy of SearchApiMultiQuery
File
- ./
search_api_multi.query.inc, line 323
View source
class SearchApiMultiQuery implements SearchApiMultiQueryInterface {
/**
* All indexes which are used in this search.
*
* This is first loaded with all indexes, and only restricted to the used ones
* during preExecute().
*
* @var array
*/
protected $indexes = array();
/**
* The indexes which are currently used in this search.
*
* This collects the index IDs (in the keys) of indexes as they are used in
* the search, so the appropriate ones can be kept in $this->indexes during
* preExecute().
*
* @var array
*/
protected $used_indexes = array();
/**
* All indexes which are used in this search, ordered by their servers.
*
* The array contains server machine names mapped to an array of all their
* searched indexes.
*
* @var array
*/
protected $servers = array();
/**
* The search keys. If NULL, this will be a filter-only search.
*
* @var mixed
*/
protected $keys;
/**
* The unprocessed search keys, as passed to the keys() method.
*
* @var mixed
*/
protected $orig_keys;
/**
* The fields that will be searched for the keys.
*
* @var array|null
*/
protected $fields;
/**
* The fields that will be searched, grouped by index.
*
* @var array
*/
protected $index_fields = array();
/**
* The search filter associated with this query.
*
* @var SearchApiQueryFilterInterface
*/
protected $filter;
/**
* The sort associated with this query.
*
* @var array
*/
protected $sort = array();
/**
* Search options configuring this query.
*
* @var array
*/
protected $options;
/**
* Flag for whether preExecute() was already called for this query.
*
* @var bool
*/
protected $pre_execute = FALSE;
/**
* {@inheritdoc}
*/
public function __construct(array $options = array()) {
if (isset($options['parse mode'])) {
$modes = $this
->parseModes();
if (!isset($modes[$options['parse mode']])) {
throw new SearchApiException(t('Unknown parse mode: @mode.', array(
'@mode' => $options['parse mode'],
)));
}
}
$this->options = $options + array(
'conjunction' => 'AND',
'parse mode' => 'terms',
'filter class' => 'SearchApiQueryFilter',
'search id' => __CLASS__,
);
$this->filter = $this
->createFilter('AND');
$this->indexes = search_api_index_load_multiple(FALSE, array(
'enabled' => TRUE,
));
foreach ($this->indexes as $index_id => $index) {
$this->servers[$index->server][$index_id] = $index;
}
}
/**
* {@inheritdoc}
*/
public function parseModes() {
$modes['direct'] = array(
'name' => t('Direct query'),
'description' => t("Don't parse the query, just hand it to the search server unaltered. " . "Might fail if the query contains syntax errors in regard to the specific server's query syntax."),
);
$modes['single'] = array(
'name' => t('Single term'),
'description' => t('The query is interpreted as a single keyword, maybe containing spaces or special characters.'),
);
$modes['terms'] = array(
'name' => t('Multiple terms'),
'description' => t('The query is interpreted as multiple keywords seperated by spaces. ' . 'Keywords containing spaces may be "quoted". Quoted keywords must still be seperated by spaces.'),
);
return $modes;
}
/**
* Parses the keys string according to a certain parse mode.
*
* @param string|array|null $keys
* The keys as passed to keys().
* @param string $mode
* The parse mode to use. Must be one of the keys from parseModes().
*
* @return string|array|null
* The parsed keys.
*/
protected function parseKeys($keys, $mode) {
if ($keys == NULL || is_array($keys)) {
return $keys;
}
$keys = '' . $keys;
switch ($mode) {
case 'direct':
return $keys;
case 'single':
return array(
'#conjunction' => $this->options['conjunction'],
$keys,
);
case 'terms':
$ret = explode(' ', $keys);
$ret['#conjunction'] = $this->options['conjunction'];
$quoted = FALSE;
$str = '';
foreach ($ret as $k => $v) {
if (!$v) {
continue;
}
if ($quoted) {
if ($v[drupal_strlen($v) - 1] == '"') {
$v = substr($v, 0, -1);
$str .= ' ' . $v;
$ret[$k] = $str;
$quoted = FALSE;
}
else {
$str .= ' ' . $v;
unset($ret[$k]);
}
}
elseif ($v[0] == '"') {
$len = drupal_strlen($v);
if ($len > 1 && $v[$len - 1] == '"') {
$ret[$k] = substr($v, 1, -1);
}
else {
$str = substr($v, 1);
$quoted = TRUE;
unset($ret[$k]);
}
}
}
if ($quoted) {
$ret[] = $str;
}
return array_filter($ret);
default:
throw new SearchApiException(t('Unrecognized parse mode %mode.', array(
'%mode' => $mode,
)));
}
}
/**
* {@inheritdoc}
*/
public function createFilter($conjunction = 'AND', array $tags = array()) {
$filter_class = $this->options['filter class'];
return new $filter_class($conjunction, $tags);
}
/**
* {@inheritdoc}
*/
public function keys($keys = NULL) {
$this->orig_keys = $keys;
if (isset($keys)) {
$this->keys = $this
->parseKeys($keys, $this->options['parse mode']);
}
else {
$this->keys = NULL;
}
return $this;
}
/**
* {@inheritdoc}
*/
public function fields($fields = NULL) {
$this->index_fields = array();
if ($fields) {
foreach ($fields as $spec) {
list($index_id, $field) = explode(':', $spec, 2);
$index = $this->indexes[$index_id];
if (empty($index->options['fields'][$field]) || !search_api_is_text_type($index->options['fields'][$field]['type'])) {
throw new SearchApiException(t('Trying to search on field @field which is no indexed fulltext field.', array(
'@field' => $field,
)));
}
$this->used_indexes[$index_id] = TRUE;
$this->index_fields[$index_id][] = $field;
}
}
$this->fields = $fields;
return $this;
}
/**
* {@inheritdoc}
*/
public function filter(SearchApiQueryFilterInterface $filter) {
$this->filter
->filter($filter);
$indexes = $this
->checkFilterIndexes($filter);
$this->used_indexes += $indexes;
// Since the filter is added with AND to the query, the query will be
// restricted to the indexes encountered within it.
$this->indexes = array_intersect_key($this->indexes, $indexes);
return $this;
}
/**
* Checks a filter object for filters on the used indexes.
*
* @param SearchApiQueryFilterInterface $filter
* The filter whose indexes should be added.
*
* @return array
* An array mapping the machine names of all indexes used in the filter to
* TRUE.
*/
protected function checkFilterIndexes(SearchApiQueryFilterInterface $filter) {
$indexes = array();
// Remember all the indexes of fields used in any filters, so we can later
// restrict the search to only those. Also, restrict the search correctly if
// the "search_api_multi_index" field is used.
foreach ($filter
->getFilters() as $f) {
if (is_array($f)) {
if ($f[0] == 'search_api_multi_index') {
if ($f[2] == '=') {
$indexes[$f[1]] = TRUE;
}
else {
foreach ($this->indexes as $id => $index) {
if ($id != $f[1]) {
$indexes[$id] = TRUE;
}
}
}
}
elseif ($f[2] != '<>' && strpos($f[0], ':')) {
list($index_id) = explode(':', $f[0], 2);
$indexes[$index_id] = TRUE;
}
}
else {
$indexes += $this
->checkFilterIndexes($f);
}
}
return $indexes;
}
/**
* {@inheritdoc}
*/
public function condition($field, $value, $operator = '=') {
if ($field == 'search_api_multi_index') {
if ($operator == '=') {
if (isset($this->indexes[$value])) {
$this->indexes = array(
$value => $this->indexes[$value],
);
}
else {
throw new SearchApiException(t('Trying to filter multi-index query on two indexes simultaneously.'));
}
}
else {
unset($this->indexes[$value]);
}
}
else {
$this->filter
->condition($field, $value, $operator);
if ($operator != '<>' && strpos($field, ':')) {
list($index_id) = explode(':', $field, 2);
$this->used_indexes[$index_id] = TRUE;
}
}
return $this;
}
/**
* {@inheritdoc}
*/
public function sort($field, $order = 'ASC') {
if ($field != 'search_api_relevance' && $field != 'search_api_id') {
list($index_id, $f) = explode(':', $field, 2);
$index = $this->indexes[$index_id];
$fields = $index->options['fields'];
if (empty($fields[$f])) {
throw new SearchApiException(t('Trying to sort on unknown field @field.', array(
'@field' => $f,
)));
}
$type = $fields[$f]['type'];
if (search_api_is_list_type($type) || search_api_is_text_type($type)) {
throw new SearchApiException(t('Trying to sort on field @field of illegal type @type.', array(
'@field' => $f,
'@type' => $type,
)));
}
$this->used_indexes[$index_id] = TRUE;
}
$order = strtoupper(trim($order)) == 'DESC' ? 'DESC' : 'ASC';
$this->sort[$field] = $order;
return $this;
}
/**
* {@inheritdoc}
*/
public function range($offset = NULL, $limit = NULL) {
$this->options['offset'] = $offset;
$this->options['limit'] = $limit;
return $this;
}
/**
* Implements SearchApiMultiQueryInterface::execute().
*
* Uses a server's searchMultiple() method, where possible.
*/
public final function execute() {
$start = microtime(TRUE);
// Call pre-execute hook.
$this
->preExecute();
// Let modules alter the query.
drupal_alter('search_api_multi_query', $this);
$pre_search = microtime(TRUE);
// Execute query.
if (count($this->servers) == 1) {
$server = search_api_server_load(key($this->servers));
if ($server && $server
->supportsFeature('search_api_multi')) {
$response = $server
->searchMultiple($this);
}
}
if (!isset($response)) {
$response = $this
->searchMultiple();
}
$post_search = microtime(TRUE);
// Call post-execute hook.
$this
->postExecute($response);
$end = microtime(TRUE);
$response['performance']['complete'] = $end - $start;
$response['performance']['hooks'] = $response['performance']['complete'] - ($post_search - $pre_search);
// Store search for later retrieval for facets, etc.
search_api_multi_current_search(NULL, $this, $response);
return $response;
}
/**
* Helper method for adding a language filter.
*
* @param array $languages
* The languages which the query should include.
*/
protected function addLanguages(array $languages) {
if (array_search(LANGUAGE_NONE, $languages) === FALSE) {
$languages[] = LANGUAGE_NONE;
}
$filter = $this
->createFilter('OR');
foreach ($languages as $lang) {
foreach ($this->indexes as $index_id => $index) {
$filter
->condition("{$index_id}:search_api_language", $lang);
}
}
$this
->filter($filter);
}
/**
* Searches multiple indexes with this query.
*
* Workaround if there is no server's searchMultiple() method available.
*
* @return array
* Search results as specified by SearchApiMultiQueryInterface::execute().
*/
protected function searchMultiple() {
// Prepare options/range.
$options = $this->options;
if (!empty($options['offset']) || isset($options['limit'])) {
$options['limit'] = isset($options['limit']) ? $options['offset'] + $options['limit'] : NULL;
$options['offset'] = 0;
}
// Prepare a normal Search API query for all contained indexes.
/** @var SearchApiQuery[] $queries */
$queries = array();
foreach ($this
->getIndexes() as $index_id => $index) {
try {
$queries[$index_id] = search_api_query($index_id, $options);
} catch (SearchApiException $e) {
watchdog_exception('search_api_multi', $e);
}
}
// Set the filters appropriately.
$this
->addFilters($this->filter
->getFilters(), $queries, $queries);
// Prepare and execute the search on every index available.
foreach ($queries as $index_id => $query) {
if (isset($this->orig_keys)) {
if (empty($this->index_fields[$index_id])) {
continue;
}
$query
->keys($this->orig_keys);
$query
->fields($this->index_fields[$index_id]);
}
foreach ($this->sort as $field => $order) {
if (strpos($field, ':') !== FALSE) {
list($field_index_id, $field) = explode(':', $field, 2);
if ($field_index_id != $index_id) {
continue;
}
}
$query
->sort($field, $order);
}
$response = $query
->execute();
if (!empty($response['results'])) {
// Adapt the results array to the multi-index format.
$results = array();
foreach ($response['results'] as $key => $result) {
$key = "{$index_id}:{$key}";
$results[$key] = $result;
$results[$key]['index_id'] = $index_id;
}
$response['results'] = $results;
}
if (!isset($return)) {
$return = array(
'result count' => 0,
'results' => array(),
'performance' => array(),
);
}
// Add the new result count.
$return['result count'] += $response['result count'];
// Merge results.
if (!empty($response['results'])) {
$return['results'] = array_merge($return['results'], $response['results']);
}
// Merge performance.
if (!empty($response['performance'])) {
foreach ($response['performance'] as $measure => $time) {
$return['performance'] += array(
$measure => 0,
);
$return['performance'][$measure] += $time;
}
}
// Merge any additional keys. We can only guess what to do here, but we
// opt to merge array-valued keys together, and store all other kinds of
// data in a new array keyed by index ID.
unset($response['result count'], $response['results'], $response['performance']);
foreach ($response as $key => $value) {
if (is_array($value)) {
$return[$key] = isset($return[$key]) ? array_merge($value, $return[$key]) : $value;
}
else {
$return[$key][$index_id] = $value;
}
}
}
if (isset($return)) {
if (!empty($return['results'])) {
// Add default sorting by score, if it isn't included already.
if ($this->keys && !isset($this->sort['search_api_relevance'])) {
$this->sort['search_api_relevance'] = 'DESC';
}
// Sort the results.
if ($this->sort) {
$this
->ensureSortFields($return['results']);
uasort($return['results'], array(
$this,
'compareResults',
));
}
// Apply range.
$offset = $this
->getOption('offset', 0);
$limit = $this
->getOption('limit', NULL);
$return['results'] = array_slice($return['results'], $offset, $limit, TRUE);
}
return $return;
}
return array(
'result count' => 0,
);
}
/**
* Helper method for adding a filter to index-specific queries.
*
* @param SearchApiQueryFilterInterface[]|array[] $filters
* An array of filters to add, as returned by
* SearchApiQueryFilterInterface::getFilters().
* @param SearchApiQuery[] $parents
* The query or filter objects to which the filters should be applied, keyed
* by index ID.
* @param SearchApiQuery[] $queries
* The queries used, keyed by index ID.
*/
protected function addFilters(array $filters, array $parents, array $queries) {
foreach ($filters as $filter) {
if (is_array($filter)) {
if ($filter[0] == 'search_api_multi_index') {
continue;
}
list($index_id, $field) = explode(':', $filter[0], 2);
if (!empty($parents[$index_id])) {
$parents[$index_id]
->condition($field, $filter[1], $filter[2]);
}
}
else {
/** @var SearchApiQueryFilterInterface[] $nested */
$nested = array();
foreach ($parents as $index_id => $query) {
$nested[$index_id] = $queries[$index_id]
->createFilter($filter
->getConjunction());
}
$this
->addFilters($filter
->getFilters(), $nested, $queries);
foreach ($nested as $index_id => $nested_filter) {
if ($nested_filter
->getFilters()) {
$parents[$index_id]
->filter($nested_filter);
}
}
}
}
}
/**
* Ensure that all results have all fields needed for sorting.
*
* @param array $results
* The results array, as in the 'results' key of the return value of
* SearchApiMultiQueryInterface::execute().
*/
protected function ensureSortFields(array &$results) {
$sort = array_keys($this->sort);
// Eliminate special fields which are always included.
foreach ($sort as $i => $key) {
if ($key == 'search_api_id' || $key == 'search_api_relevance') {
unset($sort[$i]);
}
}
if (!$sort) {
return;
}
// Determine what fields we need from items of each index.
$fields = array();
foreach ($sort as $key) {
list($index_id, $field) = explode(':', $key, 2);
if (!empty($this->indexes[$index_id])) {
$fields[$index_id][$field] = $this->indexes[$index_id]->options['fields'][$field];
}
}
if (!$fields) {
return;
}
// Determine for which items we need the entity.
$to_load = array();
foreach ($results as $i => $result) {
$results[$i] = $result += array(
'fields' => array(),
'entity' => NULL,
);
if (empty($fields[$result['index_id']]) || $result['entity']) {
continue;
}
foreach ($fields[$result['index_id']] as $field => $info) {
if (!array_key_exists($field, $result['fields'])) {
$to_load[$this->indexes[$result['index_id']]->item_type][$i] = $result['id'];
break;
}
}
}
// Load items, as necessary.
foreach ($to_load as $type => $ids) {
$type_items = search_api_get_datasource_controller($type)
->loadItems($ids);
foreach ($ids as $i => $id) {
if (isset($type_items[$id])) {
$results[$i]['entity'] = $type_items[$id];
}
}
}
// Now extract the fields for each item.
foreach ($results as $i => $result) {
if (empty($fields[$result['index_id']])) {
continue;
}
$item_fields = $fields[$result['index_id']];
if (empty($result['entity'])) {
$results[$i]['fields'] += array_fill_keys(array_keys($item_fields), NULL);
continue;
}
$item_fields = array_diff_key($item_fields, $result['fields']);
if ($item_fields) {
$wrapper = $this->indexes[$result['index_id']]
->entityWrapper($result['entity']);
$item_fields = search_api_extract_fields($wrapper, $item_fields);
foreach ($item_fields as $field => $info) {
$results[$i]['fields'][$field] = $info['value'];
}
}
}
}
/**
* Compare two result arrays.
*
* Callback for uasort() within searchMultiple().
*
* @param array $a
* One result.
* @param array $b
* The other result.
*
* @return int
* A negative number if $a should come before $b, 0 if both compare equal
* and a positive number otherwise.
*/
protected function compareResults(array &$a, array &$b) {
foreach ($this->sort as $key => $order) {
// Get the sorting for this specific field.
if ($key == 'search_api_relevance') {
$comp = $a['score'] - $b['score'];
}
elseif ($key == 'search_api_id') {
if (is_numeric($a['id']) && is_numeric($b['id'])) {
$comp = $a['id'] - $b['id'];
}
else {
$comp = strnatcasecmp($a['id'], $b['id']);
}
}
else {
list($index_id, $field) = explode(':', $key, 2);
$a_applies = $a['index_id'] == $index_id;
$b_applies = $b['index_id'] == $index_id;
if ($a_applies == $b_applies) {
if (!$a_applies) {
continue;
}
$value_a = $a['fields'][$field];
$value_b = $b['fields'][$field];
if (is_numeric($value_a) && is_numeric($value_b)) {
$comp = $value_a - $value_b;
}
else {
$comp = strnatcasecmp($value_a, $value_b);
}
}
else {
$comp = $a_applies ? -1 : 1;
// When the sort only applies to one of the two results, we always
// want it in front of the other, regardless of $order.
$order = 'ASC';
}
}
// Now apply the specified order and either return or continue.
if (!$comp) {
continue;
}
return (int) ($order == 'ASC' ? $comp : -$comp);
}
return 0;
}
/**
* Pre-execute hook for modifying search behaviour.
*/
public function preExecute() {
// Make sure to only execute this once per query.
if (!$this->pre_execute) {
$this->pre_execute = TRUE;
// Add filter for languages.
if (isset($this->options['languages'])) {
$this
->addLanguages($this->options['languages']);
}
// Filter indexes to those used. If no index was explicitly used, include
// all of them.
if ($this->used_indexes) {
$this->indexes = array_intersect_key($this->indexes, $this->used_indexes);
}
// Add fulltext fields, unless set.
if ($this->fields === NULL) {
$this->fields = $this->index_fields = array();
foreach ($this->indexes as $index_id => $index) {
foreach ($index
->getFulltextFields() as $f) {
$this->fields[] = "{$index_id}:{$f}";
$this->index_fields[$index_id][] = $f;
}
}
}
elseif ($this->keys) {
$this->indexes = array_intersect_key($this->indexes, $this->index_fields);
}
// Filter the $servers property according to the used indexes.
foreach ($this->servers as $server_id => $indexes) {
foreach ($indexes as $index_id => $index) {
if (!isset($this->indexes[$index_id])) {
unset($this->servers[$server_id][$index_id]);
}
}
}
$this->servers = array_filter($this->servers);
}
}
/**
* Post-execute hook for modifying search behaviour.
*
* @param array $results
* The results returned by the server, which may be altered.
*/
public function postExecute(array &$results) {
}
/**
* {@inheritdoc}
*/
public function getIndexes() {
return $this->indexes;
}
/**
* {@inheritdoc}
*/
public function &getKeys() {
return $this->keys;
}
/**
* {@inheritdoc}
*/
public function getOriginalKeys() {
return $this->orig_keys;
}
/**
* {@inheritdoc}
*/
public function &getFields() {
return $this->fields;
}
/**
* {@inheritdoc}
*/
public function getFilter() {
return $this->filter;
}
/**
* {@inheritdoc}
*/
public function &getSort() {
return $this->sort;
}
/**
* {@inheritdoc}
*/
public function getOption($name, $default = NULL) {
return isset($this->options[$name]) ? $this->options[$name] : $default;
}
/**
* {@inheritdoc}
*/
public function setOption($name, $value) {
$old = $this
->getOption($name);
$this->options[$name] = $value;
return $old;
}
/**
* {@inheritdoc}
*/
public function &getOptions() {
return $this->options;
}
/**
* Implements the magic __toString() method to simplify debugging.
*/
public function __toString() {
$ret = '';
if ($this->indexes) {
$indexes = array();
foreach ($this->indexes as $index) {
$indexes[] = $index->machine_name;
}
$ret .= 'Indexes: ' . implode(', ', $indexes) . "\n";
}
$ret .= 'Keys: ' . str_replace("\n", "\n ", var_export($this->orig_keys, TRUE)) . "\n";
if (isset($this->keys)) {
$ret .= 'Parsed keys: ' . str_replace("\n", "\n ", var_export($this->keys, TRUE)) . "\n";
$ret .= 'Searched fields: ' . (isset($this->fields) ? implode(', ', $this->fields) : '[ALL]') . "\n";
}
if ($filter = (string) $this->filter) {
$filter = str_replace("\n", "\n ", $filter);
$ret .= "Filters:\n {$filter}\n";
}
if ($this->sort) {
$sort = array();
foreach ($this->sort as $field => $order) {
$sort[] = "{$field} {$order}";
}
$ret .= 'Sorting: ' . implode(', ', $sort) . "\n";
}
$options = $this
->sanitizeOptions($this->options);
$options = str_replace("\n", "\n ", var_export($options, TRUE));
$ret .= 'Options: ' . $options . "\n";
return $ret;
}
/**
* Sanitizes an array of options in a way that plays nice with var_export().
*
* @param array $options
* An array of options.
*
* @return array
* The sanitized options.
*/
protected function sanitizeOptions(array $options) {
foreach ($options as $key => $value) {
if (is_object($value)) {
$options[$key] = 'object (' . get_class($value) . ')';
}
elseif (is_array($value)) {
$options[$key] = $this
->sanitizeOptions($value);
}
}
return $options;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
SearchApiMultiQuery:: |
protected | property | The fields that will be searched for the keys. | |
SearchApiMultiQuery:: |
protected | property | The search filter associated with this query. | |
SearchApiMultiQuery:: |
protected | property | All indexes which are used in this search. | |
SearchApiMultiQuery:: |
protected | property | The fields that will be searched, grouped by index. | |
SearchApiMultiQuery:: |
protected | property | The search keys. If NULL, this will be a filter-only search. | |
SearchApiMultiQuery:: |
protected | property | Search options configuring this query. | |
SearchApiMultiQuery:: |
protected | property | The unprocessed search keys, as passed to the keys() method. | |
SearchApiMultiQuery:: |
protected | property | Flag for whether preExecute() was already called for this query. | |
SearchApiMultiQuery:: |
protected | property | All indexes which are used in this search, ordered by their servers. | |
SearchApiMultiQuery:: |
protected | property | The sort associated with this query. | |
SearchApiMultiQuery:: |
protected | property | The indexes which are currently used in this search. | |
SearchApiMultiQuery:: |
protected | function | Helper method for adding a filter to index-specific queries. | |
SearchApiMultiQuery:: |
protected | function | Helper method for adding a language filter. | |
SearchApiMultiQuery:: |
protected | function | Checks a filter object for filters on the used indexes. | |
SearchApiMultiQuery:: |
protected | function | Compare two result arrays. | |
SearchApiMultiQuery:: |
public | function |
Add a new ($field $operator $value) condition filter. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Method for creating a filter to use with this query object. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
protected | function | Ensure that all results have all fields needed for sorting. | |
SearchApiMultiQuery:: |
final public | function |
Implements SearchApiMultiQueryInterface::execute(). Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Sets the fields that will be searched for the search keys. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Adds a subfilter to this query's filter. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Retrieves the searched fulltext fields. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Retrieves the query's filter object. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Retrieves the searched indexes. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Retrieves the search keys. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Retrieves a single option. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Retrieves all options for this query. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Retrieves the original, unprocessed search keys. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Retrieves the set sorts. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Sets the keys to search for. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
protected | function | Parses the keys string according to a certain parse mode. | |
SearchApiMultiQuery:: |
public | function |
Retrieve a list of all parse modes supported by this query class. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function | Post-execute hook for modifying search behaviour. | |
SearchApiMultiQuery:: |
public | function | Pre-execute hook for modifying search behaviour. | |
SearchApiMultiQuery:: |
public | function |
Adds a range of results to return. This will be saved in the query's
options. If called without parameters, this will remove all range
restrictions previously set. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
protected | function | Sanitizes an array of options in a way that plays nice with var_export(). | |
SearchApiMultiQuery:: |
protected | function | Searches multiple indexes with this query. | |
SearchApiMultiQuery:: |
public | function |
Sets an option. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Add a sort directive to this search query. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function |
Constructs a new query object. Overrides SearchApiMultiQueryInterface:: |
|
SearchApiMultiQuery:: |
public | function | Implements the magic __toString() method to simplify debugging. |