Skip to content

Instantly share code, notes, and snippets.

@antillas21
Created July 23, 2012 17:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antillas21/3164950 to your computer and use it in GitHub Desktop.
Save antillas21/3164950 to your computer and use it in GitHub Desktop.
elasticsearch - playing around

Explicación

La idea era agregar tiendas en una tabla, indexarlas via elasticsearch, y correr búsquedas vía un simple text_input como google.

Obviamente los resultados debían ser ordenados por default según su ranking. Aquellos registros con un ranking más alto, aparecerían primero.

Store es el modelo que se indexa vía elasticsearch. No hay mucho que hacer, sólo incluir unos módulos que provee la gema tire.

Con esta integración, cada vez que se crea un registro. Se indexa automáticamente. Tire, proporciona un rake task para importar registros existentes, que también sirve para re-importar registros a voluntad (digamos, en un cron job, para que tengamos los valores más recientes del ranking de cada registro). $ rake environment tire:import CLASS=Store FORCE=true

A través de un override del método :search que provee tire al ser incluido en un modelo, podemos crear nuestro query por default, con las opciones que necesitamos, ejemplo: default sort, y default filter.

# ... gems
# para este demo, al guardar un registro, vía geocoder obtenía su geolocalizaicón
gem 'geocoder'
# Ruby API & DSL, with ActiveRecord/ActiveModel integration.
gem 'tire'
# elasticsearch requiere que el modelo a indexar soporte paginación,
# lo podemos lograr con will_paginate o kaminari (your choice)
gem 'will_paginate'
http://localhost:9200/stores/store?_search
{
"took":1,
"timed_out":false,
"_shards": {
"total":5,
"successful":5,
"failed":0
},
"hits": {
"total":1,
"max_score":1.0,
"hits":[
{
"_index": "stores",
"_type": "store",
"_id":"1",
"_score":1.0,
"_source" : {
"venue": {
"title": "Pizzeria Pomodoro",
"description": "Lorem impsum dolor sit ammet",
"ranking": "9.56869"
"location": ["32.6646049197085","-115.4961678802915"]
}
}
},
{
"_index": "stores",
"_type": "store",
"_id":"1",
"_score":1.0,
"_source" : {
"venue": {
"title": "Tony's Pizza Joint",
"description": "Lorem impsum dolor sit ammet",
"ranking": "7.56869"
"location": ["32.69579101970849","-115.4979209802915"]
}
}
}
]
}
}
class Store
# fields: :name, :full_address, :description, :ranking, :latitude, :longitude
attr_accessible :name, :full_address, :description, :ranking
geocode_by :full_address
after_validation :geocode
include Tire::Model::Search
include Tire::Model::Callbacks
mapping do
indexes :id, :index => :not_analyzed
indexes :name, :type => 'string', :analyzer => 'snowball'
indexes :description, :analyzer => 'snowball'
indexes :full_address, :type => 'string'
indexes :ranking, :type => 'float'
indexes :location, :type => 'geo_point'
end
def location
[latitude, longitude]
end
def calculate_ranking
# codigo para calcular el social ranking
# self.update_attribute(:ranking, result)
end
def to_indexed_json
to_json(methods: [:location])
end
def self.search(params)
tire.search do
query { string params[:query] } if params[:query].present?
filter {
# aquí es donde debe agregarse el query para filtrar por geo-ubicación
# ejemplo:
filter :geo_distance, location: "41,-71", distance: '100km'
# necesita pulirse, este ejemplo está tomado del wiki de la gema tire
# por alguna razón no está bien construido. Necesita investigar más.
}
sort { by :ranking, "desc" }
end
end
end
class StoresController < ApplicationController
def index
@stores = Store.search(params)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment