|
| 1 | +require 'ansi' |
| 2 | +require 'sqlite3' |
| 3 | +require 'active_record' |
| 4 | +require 'elasticsearch/model' |
| 5 | + |
| 6 | +ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT) |
| 7 | +ActiveRecord::Base.establish_connection( adapter: 'sqlite3', database: ":memory:" ) |
| 8 | + |
| 9 | +ActiveRecord::Schema.define(version: 1) do |
| 10 | + create_table :articles do |t| |
| 11 | + t.string :title |
| 12 | + t.date :published_at |
| 13 | + t.timestamps |
| 14 | + end |
| 15 | +end |
| 16 | + |
| 17 | +class Article < ActiveRecord::Base |
| 18 | + include Elasticsearch::Model |
| 19 | + include Elasticsearch::Model::Callbacks |
| 20 | + |
| 21 | + article_es_settings = { |
| 22 | + index: { |
| 23 | + analysis: { |
| 24 | + filter: { |
| 25 | + autocomplete_filter: { |
| 26 | + type: "edge_ngram", |
| 27 | + min_gram: 1, |
| 28 | + max_gram: 20 |
| 29 | + } |
| 30 | + }, |
| 31 | + analyzer:{ |
| 32 | + autocomplete: { |
| 33 | + type: "custom", |
| 34 | + tokenizer: "standard", |
| 35 | + filter: ["lowercase", "autocomplete_filter"] |
| 36 | + } |
| 37 | + } |
| 38 | + } |
| 39 | + } |
| 40 | + } |
| 41 | + |
| 42 | + settings article_es_settings do |
| 43 | + mapping do |
| 44 | + indexes :title |
| 45 | + indexes :suggestable_title, type: 'string', analyzer: 'autocomplete' |
| 46 | + end |
| 47 | + end |
| 48 | + |
| 49 | + def as_indexed_json(options={}) |
| 50 | + as_json.merge(suggestable_title: title) |
| 51 | + end |
| 52 | +end |
| 53 | + |
| 54 | +Article.__elasticsearch__.client = Elasticsearch::Client.new log: true |
| 55 | + |
| 56 | +# Create index |
| 57 | + |
| 58 | +Article.__elasticsearch__.create_index! force: true |
| 59 | + |
| 60 | +# Store data |
| 61 | + |
| 62 | +Article.delete_all |
| 63 | +Article.create title: 'Foo' |
| 64 | +Article.create title: 'Bar' |
| 65 | +Article.create title: 'Foo Foo' |
| 66 | +Article.__elasticsearch__.refresh_index! |
| 67 | + |
| 68 | +# Search and suggest |
| 69 | +fulltext_search_response = Article.search(query: { match: { title: 'foo'} } ) |
| 70 | + |
| 71 | +puts "", "Article search for 'foo':".ansi(:bold), |
| 72 | + fulltext_search_response.to_a.map { |d| "Title: #{d.title}" }.inspect.ansi(:bold, :yellow), |
| 73 | + "" |
| 74 | + |
| 75 | +fulltext_search_response_2 = Article.search(query: { match: { title: 'fo'} } ) |
| 76 | + |
| 77 | +puts "", "Article search for 'fo':".ansi(:bold), |
| 78 | + fulltext_search_response_2.to_a.map { |d| "Title: #{d.title}" }.inspect.ansi(:bold, :red), |
| 79 | + "" |
| 80 | + |
| 81 | +autocomplete_search_response = Article.search(query: { match: { suggestable_title: { query: 'fo', analyzer: 'standard'} } } ) |
| 82 | + |
| 83 | +puts "", "Article autocomplete for 'fo':".ansi(:bold), |
| 84 | + autocomplete_search_response.to_a.map { |d| "Title: #{d.suggestable_title}" }.inspect.ansi(:bold, :green), |
| 85 | + "" |
| 86 | + |
| 87 | +puts "", "Text 'Foo Bar' analyzed with the default analyzer:".ansi(:bold), |
| 88 | + Article.__elasticsearch__.client.indices.analyze( |
| 89 | + index: Article.__elasticsearch__.index_name, |
| 90 | + field: 'title', |
| 91 | + text: 'Foo Bar')['tokens'].map { |t| t['token'] }.inspect.ansi(:bold, :yellow), |
| 92 | + "" |
| 93 | + |
| 94 | +puts "", "Text 'Foo Bar' analyzed with the autocomplete filter:".ansi(:bold), |
| 95 | + Article.__elasticsearch__.client.indices.analyze( |
| 96 | + index: Article.__elasticsearch__.index_name, |
| 97 | + field: 'suggestable_title', |
| 98 | + text: 'Foo Bar')['tokens'].map { |t| t['token'] }.inspect.ansi(:bold, :yellow), |
| 99 | + "" |
| 100 | + |
| 101 | +require 'pry'; binding.pry; |
0 commit comments