Apache Solr Proximity Search and sort by Distance

by Micah   Last Updated January 11, 2019 12:07 PM

I wrote a custom module to perform a search of an index I created using Search API and Search API Solr Search. The search is a proximity search that finds the closest locations using a bounding box, but I can't figure out how to SORT the results I get back by the closest. Here is my module code in entirety:

<?php

function s_test() {

  $index      = search_api_index_load("articles");
  $query      = new SearchApiQuery($index);

  $lat        = 41.920110;
  $lon        = -87.680433;

  //get min/max lat and long
  $check_radius = 25; // radius of bounding circle in miles
  $earth_radius = 3960;  // earth's mean radius, miles

  // first-cut bounding box (in degrees)
  $max_lat = $lat + rad2deg($check_radius/$earth_radius);
  $min_lat = $lat - rad2deg($check_radius/$earth_radius);

  // compensate for degrees longitude getting smaller with increasing latitude
  $max_lon = $lon + rad2deg($check_radius/$earth_radius/cos(deg2rad($lat)));
  $min_lon = $lon - rad2deg($check_radius/$earth_radius/cos(deg2rad($lat)));

  // set the bounding box
  $filter = $query->createFilter('AND');
  $filter->condition('latitude', $max_lat, '<=');
  $filter->condition('latitude', $min_lat, '>=');
  $filter->condition('longitude', $max_lon, '<=');
  $filter->condition('longitude', $min_lon, '>=');
  $query->filter($filter);

  // run query
  $data       = $query->execute();
  $results    = $data['results'];

  print_r($results);
}

function s_index() {
  $index      = search_api_index_load("articles");

  $index->reindex();
  search_api_index_items($index);
  print '<pre>';
  print_r($index);
  print '</pre>';
}

function test_query_menu() {
  //create the search page
  $items['test-search'] = array(
    'title' => t('Search'),
    'page callback' => 's_test',
    'access callback' => TRUE,
    'type' => MENU_NORMAL_ITEM
  );
  //create a re-index page
  $items['test-index'] = array(
    'title' => t('Index'),
    'page callback' => 's_index',
    'access callback' => TRUE,
    'type' => MENU_NORMAL_ITEM
  );
  return $items;
}

/**
 * Implements hook_entity_property_info_alter().
 */
function test_query_entity_property_info_alter(&$info) {
  $info['node']['properties']['latitude'] = array(
    'type' => 'decimal',
    'label' => t('Latitude'),
    'sanitized' => TRUE,
    'getter callback' => 'test_query_search_api_property_latitude_getter_callback',
  );
  $info['node']['properties']['longitude'] = array(
    'type' => 'decimal',
    'label' => t('Longitude'),
    'sanitized' => TRUE,
    'getter callback' => 'test_query_search_api_property_longitude_getter_callback',
  );
  $info['node']['properties']['latlongpair'] = array(
    'type' => 'string',
    'label' => t('LatLong Pair'),
    'sanitized' => TRUE,
    'getter callback' => 'test_query_search_api_property_latlongpair_getter_callback',
  );
  $info['node']['properties']['logo_uri'] = array(
    'type' => 'string',
    'label' => t('LOGO URI'),
    'sanitized' => TRUE,
    'getter callback' => 'test_query_search_api_property_logo_uri_getter_callback',
  );
}

/**
 * Getter callback for latitude.
 */
function test_query_search_api_property_latitude_getter_callback($item) {
  return $item->field_address[LANGUAGE_NONE][0]['latitude']; 
}

/**
 * Getter callback for longitude.
 */
function test_query_search_api_property_longitude_getter_callback($item) {
  return $item->field_address[LANGUAGE_NONE][0]['longitude']; 
}

/**
 * Getter callback for latitude/longitude pair.
 */
function test_query_search_api_property_latlongpair_getter_callback($item) {
  return $item->field_address[LANGUAGE_NONE][0]['latitude'] . ',' . $item->field_address[LANGUAGE_NONE][0]['longitude']; 
}

/**
 * Getter callback for logo uri.
 */
function test_query_search_api_property_logo_uri_getter_callback($item) {
  return $item->field_image[LANGUAGE_NONE][0]['uri']; 
}

Basically I exposed my latitude and longitude to Solr and used those to set the bounding box and this works find to return results close to me, but I don't see any field in the results set that would allow me to sort by the node with the closest location.

I also tried installing the Search API Location module, but I still can't find anything in the results set to sort by.

I'm using Location and Location CCK module to get the lat/long.

If anyone has experience/insight with this that would be groovy.



Answers 1


Assuming you are using Drupal 7, see http://tech-tamer.com/multi-location-proximity-search-in-drupal-7-with-solr/ for some ideas and code samples.

Giles B
Giles B
December 28, 2016 17:40 PM

Related Questions


Updated May 19, 2017 03:07 AM

Updated March 08, 2017 22:07 PM

Updated April 22, 2017 23:07 PM

Updated March 10, 2017 14:07 PM

Updated June 08, 2016 08:03 AM