You are here

protected function SearchApiElasticsearchConnector::buildSearchQuery in Elasticsearch Connector 7.2

Same name and namespace in other branches
  1. 7.5 modules/elasticsearch_connector_search_api/service.inc \SearchApiElasticsearchConnector::buildSearchQuery()
  2. 7 modules/elasticsearch_connector_search_api/service.inc \SearchApiElasticsearchConnector::buildSearchQuery()

Helper function build search query().

1 call to SearchApiElasticsearchConnector::buildSearchQuery()
SearchApiElasticsearchConnector::search in modules/elasticsearch_connector_search_api/service.inc
Overrides search().

File

modules/elasticsearch_connector_search_api/service.inc, line 1203
Provides a Elasticsearch-based service class for the Search API using Elasticsearch Connector module.

Class

SearchApiElasticsearchConnector
Search service class.

Code

protected function buildSearchQuery(SearchApiQueryInterface $query) {

  // Query options.
  $query_options = $this
    ->getSearchQueryOptions($query);

  // Main query.
  $params = $query
    ->getOption('ElasticParams');
  $body =& $params['body'];

  // Set the size and from parameters.
  $body['from'] = $query_options['query_offset'];
  $body['size'] = $query_options['query_limit'];

  // Sort
  if (!empty($query_options['sort'])) {
    $body['sort'] = $query_options['sort'];
  }
  $body['fields'] = array();
  $fields =& $body['fields'];

  // Handle spellcheck if enabled
  $this
    ->buildSpellcheckQuery($query, $params);

  /**
   * $query_options['spatials']:
   * - field: The Search API field identifier of the location field. Must be indexed
   *   as type "location".
   * - lat: The latitude of the point on which this location parameter is centered.
   * - lon: The longitude of that point.
   * - radius: (optional) If results should be filtered according to their distance
   *   to the point, the maximum distance at which a point should be included (in
   *   kilometers).
   * - method: (optional) The method to use for filtering. This is backend-specific
   *   and not guaranteed to have an effect. Service classes should ignore values of
   *   this option which they don't recognize.
   */

  // Search API Location support.
  if (!empty($query_options['spatials'])) {
    foreach ($query_options['spatials'] as $i => $spatial) {
      if (empty($spatial['field']) || empty($spatial['lat']) || empty($spatial['lon'])) {
        continue;
      }

      // Shortcut to easily reuse the field and point.
      $field = $spatial['field'];
      $point = array(
        'lat' => (double) $spatial['lat'],
        'lon' => (double) $spatial['lon'],
      );

      // Prepare the filter settings.
      if (isset($spatial['radius'])) {
        $radius = (double) $spatial['radius'];
      }

      // TODO: Implement the other geo filter types.
      // TODO: Implement the functionality to have multiple filters together
      // with the geo filters.
      // // Geo bounding box filter.
      // $query_options['query_search_filter'] = array(
      //   'geo_bounding_box' => array(
      //     $spatial['field'] => array(
      //       'top_left' => array(
      //         'lat' => '',
      //         'lon' => '',
      //       ),
      //       'bottom_right' => array(
      //         'lat' => '',
      //         'lon' => '',
      //       ),
      //     ),
      //   ),
      // );
      // Geo Distance filter.
      $geo_distance_filter = array(
        'geo_distance' => array(
          'distance' => $radius . 'km',
          $spatial['field'] => $point,
        ),
      );
      if (!empty($query_options['query_search_filter'])) {
        $query_options['query_search_filter'] = array(
          'and' => array(
            $query_options['query_search_filter'],
            $geo_distance_filter,
          ),
        );
      }
      else {
        $query_options['query_search_filter'] = $geo_distance_filter;
      }

      // // Geo distance range filter.
      // $query_options['query_search_filter'] = array(
      //   'geo_distance_range' => array(
      //     'from' => '',
      //     'to' => '',
      //     $spatial['field'] => $point,
      //   ),
      // );
      // // Geo polygon filter.
      // $query_options['query_search_filter'] = array(
      //   'geo_polygon' => array(
      //     $spatial['field'] => array(
      //       'points' => array(),
      //     ),
      //   ),
      // );
      // // Geoshape filter.
      // $query_options['query_search_filter'] = array(
      //   'geo_shape' => array(
      //     $spatial['field'] => array(
      //       'shape' => array(
      //         'type' => 'envelope',
      //         'coordinates' => array(),
      //       ),
      //     ),
      //   ),
      // );
      // // Geohash cell filter.
      // $query_options['query_search_filter'] = array(
      //   'geohash_cell' => array(
      //     $spatial['field'] => $point,
      //     'precision' => '',
      //     'neighbors' => '',
      //   ),
      // );
    }
  }

  // Build the query.
  if (!empty($query_options['query_search']) && !empty($query_options['query_search_filter'])) {
    $body['query']['filtered']['query'] = $query_options['query_search'];
    $body['query']['filtered']['filter'] = $query_options['query_search_filter'];
  }
  elseif (!empty($query_options['query_search'])) {
    if (empty($body['query'])) {
      $body['query'] = array();
    }
    $body['query'] += $query_options['query_search'];
  }
  elseif (!empty($query_options['query_search_filter'])) {
    $body['filter'] = $query_options['query_search_filter'];
  }

  // TODO: Handle fields on filter query.
  if (empty($fields)) {
    unset($body['fields']);
  }
  if (empty($body['filter'])) {
    unset($body['filter']);
  }
  if (empty($query_body)) {
    $query_body['match_all'] = array();
  }

  // Preserve the options for futher manipulation if necessary.
  $query
    ->setOption('ElasticParams', $params);
  return $params;
}