You are here

protected function SearchApiMultiQuery::searchMultiple in Search API Multi-Index Searches 7

Searches multiple indexes with this query.

Workaround if there is no server's searchMultiple() method available.

Return value

array Search results as specified by SearchApiMultiQueryInterface::execute().

1 call to SearchApiMultiQuery::searchMultiple()
SearchApiMultiQuery::execute in ./search_api_multi.query.inc
Implements SearchApiMultiQueryInterface::execute().

File

./search_api_multi.query.inc, line 746

Class

SearchApiMultiQuery
Standard implementation of SearchApiMultiQueryInterface.

Code

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,
  );
}