This doc will help you to

  • Modify schema.xml so that it supports geo location values
  • WHAT/WHERE search (radius based) - instead of a single keyword based search
  • Content-type based filtration
  • Implementation of hook_apachesolr_index_document_build, hook_apachesolr_query_alter

I am not going through the steps for installing / connecting solr with drupal. A lot of articles are already available online.

Case

Typically for job/property search sites, where you have two text fields: WHAT and WHERE. I am using the apachesolr search pages for this implementation.
Example search:
WHAT: drupal architect
WHERE: Mumbai, Maharashtra, India
(basically, the 'where' is an autofill textbox - which gets data from YQL - and its cached when search is being repeated)

Schema.xml

This file helps Solr to communicate with Drupal - also a lot of configurations to indexing/storing data, etc. The schema.xml which ships with apachesolr module doesn't provide the needed support for storing and searching based on location / radius. Here is an alternative schema.xml file submitted by pwolanin which supports the needed features alternate schema.xml

Storing / indexing data

I personally used YQL to auto fill location text in the search form as well as in the node create/edit form. Will contribute this module if I get some time to generalize it. This module also saves the lat/lng values retrieved from YQL. So, each node have multiple location fields and multiple hidden lat/lng fields which gets populated in the submit method from the cache table.

So now, I have nodes which have fields populated with location name and lat/lng values. I will now hook into apachesolr_index_document_build()

function example_search_apachesolr_index_document_build($document, $entity, $entity_type, $env_id) {
  $location = array();
  $country = array();
  $lat_lng = array();
  if (isset($entity->field_address_or_location['und'])) {
    foreach ($entity->field_address_or_location['und'] as $data) {
      $location[] = $data['safe_value'];
    }
    foreach ($entity->field_address_location_lat_lng['und'] as $data) {
      $lat_lng[] = $data['safe_value'];
    }

    //Now we have the prepared arrays, just send it to Solr
    $document->locm_jem = $lat_lng;
    $document->sm_location = $location;
  }
}
//Do check the raw indexed data - to actually see its being saved or not

Now we are done with storing/indexing the data. Next step is to alter the query and search based on radius.

Query alter to search based on lat/lng values

Here I am doing a quick content-type filtration. The $_SESSION['jem_search_latlng'] is set on a custom-form submit - more on this later.

function example_search_apachesolr_query_alter($query) {
  $radius = 200; //Later I will change this to a $_SESSION value, which will make it dynamic

  if (arg(0) == 'Content-Type-A') {
    $query->addFilter("bundle", "type_a"); //Content type filtration
  }
  if (arg(0) == 'Content-Type-A' && isset($_SESSION['search_latlng'])) {
    $ll = str_replace(' ', '', $_SESSION['search_latlng']); //modifying a little to fit into solr requirements
    $geo = "{!geofilt pt = $ll sfield=locm_jem d=$radius}";
    $query->addFilter("_query_", $geo);
  }

  if (arg(0) == 'Content-Type-B') {
    $query->addFilter("bundle", "type_b");
  }
  if (arg(0) == 'Content-Type-B' && isset($_SESSION['search_latlng'])) {
    $ll = str_replace(' ', '', $_SESSION['search_latlng']);
    $geo = "{!geofilt pt = $ll sfield=locm_jem d=$radius}";
    $query->addFilter("_query_", $geo);
  }
}

That's it! we are done with Solr. Now, we need to create a custom form, put it in a block, show it the search pages and hide the default Solr search form

Creation of form and putting in a block is easy and I hope you can do it on your own. Basically its a form with two text fields. On submit, it sets

$form_state['redirect'] = 'Content-Type-B/' . $form_state['input']['what'];

and sets the $_SESSION['search_latlng']; with lat/lng vaules.

I hope this doc helps you. If you need any more info/help in this regard, just put on comments.

Comments

toiletfinder.com’s picture

What are the units of the radius?