Created
July 29, 2012 16:57
-
-
Save karmi/3200212 to your computer and use it in GitHub Desktop.
Revisions
-
karmi created this gist
Jul 29, 2012 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,141 @@ # An example of elasticsearch & Tire setup for ActiveRecord associations. # # A `Book has_many :chapters` scenario, with mapping and JSON serialization # for indexing associated models. # # Demonstrates three important caveats as of now: # # 1. You you have to use `touch: true` in the `belongs_to` declaration, # to automatically notify the parent model about the update. # # 2. You have to explicitely hook up updating elasticsearch index via # the `after_touch` callback in the parent model. # # 3. You have to disable `include_root_in_json` for proper JSON serialization. # # # Run me with: # # $ ruby active_record_associations.rb # require 'logger' require 'ansi/core' require 'active_record' require 'oj' require 'tire' def _(message=nil); puts '-'*80, ANSI.bold(message.to_s), '-'*80; end ActiveRecord::Base.logger = Logger.new(STDERR) ActiveRecord::Base.establish_connection( adapter: 'sqlite3', database: ":memory:" ) Tire.configure { logger STDERR } _ "Creating ActiveRecord schema..." ActiveRecord::Schema.define(version: 1) do create_table :books do |t| t.string :title t.timestamps end create_table :chapters do |t| t.string :text t.integer :number, :book_id t.timestamps end add_index(:chapters, :book_id) end _ "Deleting elasticsearch index..." Tire.index('books').delete # The Book class # class Book < ActiveRecord::Base has_many :chapters # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # Enable automatic saving in elasticsearch when associated objects change # after_touch() { tire.update_index } # # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # Properly serialize JSON for elasticsearch # self.include_root_in_json = false # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! include Tire::Model::Search include Tire::Model::Callbacks # Define the mapping # mapping do indexes :title, type: 'string', boost: 10, analyzer: 'snowball' indexes :created_at, type: 'date' indexes :chapters do indexes :text, analyzer: 'snowball' end end # Define the JSON serialization # def to_indexed_json to_json( include: { chapters: { only: [:text] } } ) end end # The book Chapter class # class Chapter < ActiveRecord::Base # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # Do not forget to automatically `touch` parent object from associations belongs_to :book, touch: true # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! end _ "Create book instance..." book = Book.create title: "How to impress your Rails friends with elasticsearch" book.chapters.create number: 1, text: "The world generates more and more information ..." book.chapters.create number: 2, text: "After the elasticsearch installation ..." p Book.first p Book.first.chapters _ "Refresh the index for immediate search (there's a 1 second delay by default)..." Book.tire.index.refresh _ "Search 'elasticsearch' in book titles..." results = Book.search('title:elasticsearch') puts ANSI.green( "Found: '%s'" % results.first.title ) _ "Search 'install' in chapter text..." results = Book.search('chapters.text:install') puts ANSI.green( "Found: '%s'" % results.first.title ) _ "Search 'elasticsearch' anywhere with highlighting..." results = Book.search do query { string "elasticsearch" } highlight 'title', 'chapters.text' end puts ANSI.green( "Found: '%s'" % results.first.title ), '-'*80, "Highlights: ", results.first.highlight.to_hash \ .map { |k,v| ' - ' + k.to_s + ": " + v.first.to_s } \ .map { |s| s.gsub(/<em>([^<]+)<\/em>/, ANSI.yellow + ANSI.bold + '\1' + ANSI.reset) } \ .join("\n")