How to work with locations (geo) in Tire

jasonfb edited this page Mar 4, 2013 · 9 revisions

Tire currently does not expose the (awesome!) „Geo Location and Search” support in ElasticSearch.

However, it's simple to define proper mappings for you location-based documents, and it's possible to search them, either via the DSL method by passing it a Hash, or descending a level down, and using Tire::Configuration.client.get <MY QUERY AS A HASH> method.

The following example illustrates the point:

require 'tire'
require 'active_record'

Tire.index('venues') { delete }

ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ":memory:" )

ActiveRecord::Migration.verbose = false
ActiveRecord::Schema.define(version: 1) do
  create_table :venues do |t|
    t.string   :title, :latitude, :longitude

class Venue < ActiveRecord::Base
  include Tire::Model::Search
  include Tire::Model::Callbacks

  tire do
    mapping do
      indexes :title,   type: 'string', analyzer: 'snowball'
      indexes :lat_lon, type: 'geo_point'

  # NOTE The ordering of latitude and longitude for indexing geo points is different
  # based on whether a string or an array is used. The order when using an array 
  # should be [longitude, latitude] versus for a string where it should be "latitude,longitude".
  # See The elasticsearch documentation for more information.
  def lat_lon
    [latitude, longitude].join(',')

  def to_indexed_json
    to_json(only: ['title'], methods: ['lat_lon'])

Venue.create title: 'Pizzeria Pomodoro', latitude: "41.12", longitude: "-71.34"


# Example 1: Construct the search as a Hash
query = { query: { filtered: { query: { match_all: ''} }, filter: { geo_distance: { distance: '100km', lat_lon: "41,-71" } } } }

puts "", "The query:", '-'*80, query.to_json

s = 'venues', query

puts "", "Results:", '-'*80, s.results.inspect

# Example 2: Construct the search using block syntax
s = do
  query { all }
  filter :geo_distance, lat_lon: "41,-71", distance: '100km'

puts "", "Results:", '-'*80, s.results.inspect