elasticsearch-model 2.0.1 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 13167e8201d321dd4799a378c6980f10011512e6
4
- data.tar.gz: 5e39e63bf6e3f452455d1a886d7ec07531445d49
3
+ metadata.gz: 578a444488ef68a50e4f19c87bf43c3c3d950a39
4
+ data.tar.gz: c602b0f07801e4dc864921a067a94a8fc482da75
5
5
  SHA512:
6
- metadata.gz: 426602ea75b972789acc0e51ab3a15bb16b29d6b0929fdc8907e171f7f2b41343438179e18c59a21adbf195cc7608072e9f89b6ba5811420e6bd76555465d8d8
7
- data.tar.gz: 89a06131b99b1e6f24bf585a7d2f019efe91196aa8049dc40c6ed43cf567aefefc54e0ff250582c384ffdac98e4c0b216683a8b3eebdf181b22d395bc8955437
6
+ metadata.gz: fe1dc3d34dd8cd3447160f0eaf2c0941e57058f80a5e8334b6a058bb0e3acab4b960070c0402f81d2dd976b939951e675cb907eb9a828b9a70f9853cf65c5ff9
7
+ data.tar.gz: a366fbee0a6ff94ec51202fecfcb63b159d4cc169bc4b38debb3df032cf1dd5a94514fde0da6d4c92e2f5f2ddbaef44dc5487b75e749d762136d905c963836f7
data/README.md CHANGED
@@ -302,7 +302,7 @@ response.page(2).results
302
302
  response.page(2).records
303
303
  ```
304
304
 
305
- In a Rails controller, use the the `params[:page]` parameter to paginate through results:
305
+ In a Rails controller, use the `params[:page]` parameter to paginate through results:
306
306
 
307
307
  ```ruby
308
308
  @articles = Article.search(params[:q]).page(params[:page]).records
@@ -377,6 +377,10 @@ response.results.first.title
377
377
  For proper search engine function, it's often necessary to configure the index properly.
378
378
  The `Elasticsearch::Model` integration provides class methods to set up index settings and mappings.
379
379
 
380
+ **NOTE**: Elasticsearch will automatically create an index when a document is indexed,
381
+ with default settings and mappings. Create the index in advance with the `create_index!`
382
+ method, so your index configuration is respected.
383
+
380
384
  ```ruby
381
385
  class Article
382
386
  settings index: { number_of_shards: 1 } do
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
23
23
 
24
24
  s.required_ruby_version = ">= 1.9.3"
25
25
 
26
- s.add_dependency "elasticsearch", '~> 2'
26
+ s.add_dependency "elasticsearch", '> 1'
27
27
  s.add_dependency "activesupport", '> 3'
28
28
  s.add_dependency "hashie"
29
29
 
@@ -12,12 +12,12 @@
12
12
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
13
13
 
14
14
  require 'pry'
15
- Pry.config.history.file = File.expand_path('../../tmp/elasticsearch_development.pry', __FILE__)
16
15
 
17
16
  require 'logger'
18
17
  require 'ansi/core'
19
18
  require 'active_record'
20
19
 
20
+ require 'json'
21
21
  require 'elasticsearch/model'
22
22
 
23
23
  ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT)
@@ -33,6 +33,7 @@ ActiveRecord::Schema.define(version: 1) do
33
33
 
34
34
  create_table :authors do |t|
35
35
  t.string :first_name, :last_name
36
+ t.string :department
36
37
  t.timestamps null: false
37
38
  end
38
39
 
@@ -63,7 +64,7 @@ end
63
64
  # ----- Elasticsearch client setup ----------------------------------------------------------------
64
65
 
65
66
  Elasticsearch::Model.client = Elasticsearch::Client.new log: true
66
- Elasticsearch::Model.client.transport.logger.formatter = proc { |s, d, p, m| "\e[32m#{m}\n\e[0m" }
67
+ Elasticsearch::Model.client.transport.logger.formatter = proc { |s, d, p, m| "\e[2m#{m}\n\e[0m" }
67
68
 
68
69
  # ----- Search integration ------------------------------------------------------------------------
69
70
 
@@ -84,7 +85,7 @@ module Searchable
84
85
  def as_indexed_json(options={})
85
86
  self.as_json(
86
87
  include: { categories: { only: :title},
87
- authors: { methods: [:full_name], only: [:full_name] },
88
+ authors: { methods: [:full_name, :department], only: [:full_name, :department] },
88
89
  comments: { only: :text }
89
90
  })
90
91
  end
@@ -140,7 +141,7 @@ category = Category.create title: 'One'
140
141
 
141
142
  # Create author
142
143
  #
143
- author = Author.create first_name: 'John', last_name: 'Smith'
144
+ author = Author.create first_name: 'John', last_name: 'Smith', department: 'Business'
144
145
 
145
146
  # Create article
146
147
 
@@ -161,18 +162,52 @@ article.comments.create text: 'Second comment for article One'
161
162
 
162
163
  Elasticsearch::Model.client.indices.refresh index: Elasticsearch::Model::Registry.all.map(&:index_name)
163
164
 
164
- puts "\n\e[1mArticles containing 'one':\e[0m", Article.search('one').records.to_a.map(&:inspect), ""
165
+ # Search for a term and return records
166
+ #
167
+ puts "",
168
+ "Articles containing 'one':".ansi(:bold),
169
+ Article.search('one').records.to_a.map(&:inspect),
170
+ ""
165
171
 
166
- puts "\n\e[1mModels containing 'one':\e[0m", Elasticsearch::Model.search('one').records.to_a.map(&:inspect), ""
172
+ puts "",
173
+ "All Models containing 'one':".ansi(:bold),
174
+ Elasticsearch::Model.search('one').records.to_a.map(&:inspect),
175
+ ""
167
176
 
168
- # Load model
177
+ # Difference between `records` and `results`
169
178
  #
170
- article = Article.all.includes(:categories, :authors, :comments).first
179
+ response = Article.search query: { match: { title: 'first' } }
171
180
 
172
- # ----- Pry ---------------------------------------------------------------------------------------
181
+ puts "",
182
+ "Search results are wrapped in the <#{response.class}> class",
183
+ ""
184
+
185
+ puts "",
186
+ "Access the <ActiveRecord> instances with the `#records` method:".ansi(:bold),
187
+ response.records.map { |r| "* #{r.title} | Authors: #{r.authors.map(&:full_name) } | Comment count: #{r.comments.size}" }.join("\n"),
188
+ ""
189
+
190
+ puts "",
191
+ "Access the Elasticsearch documents with the `#results` method (without touching the database):".ansi(:bold),
192
+ response.results.map { |r| "* #{r.title} | Authors: #{r.authors.map(&:full_name) } | Comment count: #{r.comments.size}" }.join("\n"),
193
+ ""
194
+
195
+ puts "",
196
+ "The whole indexed document (according to `Article#as_indexed_json`):".ansi(:bold),
197
+ JSON.pretty_generate(response.results.first._source.to_hash),
198
+ ""
173
199
 
174
- puts '', '-'*Pry::Terminal.width!
200
+ # Retrieve only selected fields from Elasticsearch
201
+ #
202
+ response = Article.search query: { match: { title: 'first' } }, _source: ['title', 'authors.full_name']
203
+
204
+ puts "",
205
+ "Retrieve only selected fields from Elasticsearch:".ansi(:bold),
206
+ JSON.pretty_generate(response.results.first._source.to_hash),
207
+ ""
208
+
209
+ # ----- Pry ---------------------------------------------------------------------------------------
175
210
 
176
211
  Pry.start(binding, prompt: lambda { |obj, nest_level, _| '> ' },
177
- input: StringIO.new("article.as_indexed_json\n"),
212
+ input: StringIO.new('response.records.first'),
178
213
  quiet: true)
@@ -18,17 +18,16 @@ class Article < ActiveRecord::Base
18
18
  include Elasticsearch::Model::Callbacks
19
19
 
20
20
  mapping do
21
- indexes :title
22
- indexes :title_suggest, type: 'completion', payloads: true
21
+ indexes :title, type: 'text' do
22
+ indexes :suggest, type: 'completion'
23
+ end
24
+ indexes :url, type: 'keyword'
23
25
  end
24
26
 
25
27
  def as_indexed_json(options={})
26
28
  as_json.merge \
27
- title_suggest: {
28
- input: title,
29
- output: title,
30
- payload: { url: "/articles/#{id}" }
31
- }
29
+ title_suggest: { input: title },
30
+ url: "/articles/#{id}"
32
31
  end
33
32
  end
34
33
 
@@ -58,12 +57,28 @@ response_2 = Article.__elasticsearch__.client.suggest \
58
57
  body: {
59
58
  articles: {
60
59
  text: 'foo',
61
- completion: { field: 'title_suggest', size: 25 }
60
+ completion: { field: 'title.suggest' }
62
61
  }
63
62
  };
64
63
 
65
64
  puts "Article suggest:".ansi(:bold),
66
- response_2['articles'].first['options'].map { |d| "#{d['text']} -> #{d['payload']['url']}" }.
65
+ response_2['articles'].first['options'].map { |d| "#{d['text']} -> #{d['_source']['url']}" }.
67
66
  inspect.ansi(:bold, :green)
68
67
 
68
+ response_3 = Article.search \
69
+ query: {
70
+ match: { title: 'foo' }
71
+ },
72
+ suggest: {
73
+ articles: {
74
+ text: 'foo',
75
+ completion: { field: 'title.suggest' }
76
+ }
77
+ },
78
+ _source: ['title', 'url']
79
+
80
+ puts "Article search with suggest:".ansi(:bold),
81
+ response_3.response['suggest']['articles'].first['options'].map { |d| "#{d['text']} -> #{d['_source']['url']}" }.
82
+ inspect.ansi(:bold, :blue)
83
+
69
84
  require 'pry'; binding.pry;
@@ -0,0 +1,101 @@
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;
@@ -1,11 +1,12 @@
1
- require 'elasticsearch'
2
-
3
- require 'hashie'
1
+ require 'hashie/mash'
4
2
 
5
3
  require 'active_support/core_ext/module/delegation'
6
4
 
5
+ require 'elasticsearch'
6
+
7
7
  require 'elasticsearch/model/version'
8
8
 
9
+ require 'elasticsearch/model/hash_wrapper'
9
10
  require 'elasticsearch/model/client'
10
11
 
11
12
  require 'elasticsearch/model/multimodel'
@@ -0,0 +1,15 @@
1
+ module Elasticsearch
2
+ module Model
3
+
4
+ # Subclass of `Hashie::Mash` to wrap Hash-like structures
5
+ # (responses from Elasticsearch, search definitions, etc)
6
+ #
7
+ # The primary goal of the subclass is to disable the
8
+ # warning being printed by Hashie for re-defined
9
+ # methods, such as `sort`.
10
+ #
11
+ class HashWrapper < ::Hashie::Mash
12
+ disable_warnings if respond_to?(:disable_warnings)
13
+ end
14
+ end
15
+ end
@@ -65,8 +65,8 @@ module Elasticsearch
65
65
  end
66
66
  end
67
67
 
68
- # Set the type to `string` by default
69
- @mapping[name][:type] ||= 'string'
68
+ # Set the type to `text` by default
69
+ @mapping[name][:type] ||= 'text'
70
70
 
71
71
  self
72
72
  end
@@ -220,15 +220,19 @@ module Elasticsearch
220
220
  # Article.__elasticsearch__.create_index! index: 'my-index'
221
221
  #
222
222
  def create_index!(options={})
223
- target_index = options.delete(:index) || self.index_name
223
+ options = options.clone
224
+
225
+ target_index = options.delete(:index) || self.index_name
226
+ settings = options.delete(:settings) || self.settings.to_hash
227
+ mappings = options.delete(:mappings) || self.mappings.to_hash
224
228
 
225
229
  delete_index!(options.merge index: target_index) if options[:force]
226
230
 
227
231
  unless index_exists?(index: target_index)
228
232
  self.client.indices.create index: target_index,
229
233
  body: {
230
- settings: self.settings.to_hash,
231
- mappings: self.mappings.to_hash }
234
+ settings: settings,
235
+ mappings: mappings }
232
236
  end
233
237
  end
234
238
 
@@ -28,7 +28,7 @@ module Elasticsearch
28
28
  #
29
29
  def response
30
30
  @response ||= begin
31
- Hashie::Mash.new(search.execute!)
31
+ HashWrapper.new(search.execute!)
32
32
  end
33
33
  end
34
34
 
@@ -63,7 +63,7 @@ module Elasticsearch
63
63
  # Returns the statistics on shards
64
64
  #
65
65
  def shards
66
- Hashie::Mash.new(response['_shards'])
66
+ HashWrapper.new(response['_shards'])
67
67
  end
68
68
 
69
69
  # Returns a Hashie::Mash of the aggregations
@@ -3,6 +3,8 @@ module Elasticsearch
3
3
  module Response
4
4
 
5
5
  class Aggregations < Hashie::Mash
6
+ disable_warnings if respond_to?(:disable_warnings)
7
+
6
8
  def initialize(attributes={})
7
9
  __redefine_enumerable_methods super(attributes)
8
10
  end
@@ -14,7 +14,7 @@ module Elasticsearch
14
14
  # @param attributes [Hash] A Hash with document properties
15
15
  #
16
16
  def initialize(attributes={})
17
- @result = Hashie::Mash.new(attributes)
17
+ @result = HashWrapper.new(attributes)
18
18
  end
19
19
 
20
20
  # Return document `_id` as `id`
@@ -3,6 +3,8 @@ module Elasticsearch
3
3
  module Response
4
4
 
5
5
  class Suggestions < Hashie::Mash
6
+ disable_warnings if respond_to?(:disable_warnings)
7
+
6
8
  def terms
7
9
  self.to_a.map { |k,v| v.first['options'] }.flatten.map {|v| v['text']}.uniq
8
10
  end
@@ -1,5 +1,5 @@
1
1
  module Elasticsearch
2
2
  module Model
3
- VERSION = "2.0.1"
3
+ VERSION = "5.0.0"
4
4
  end
5
5
  end
@@ -31,7 +31,7 @@ class Answer < ActiveRecord::Base
31
31
 
32
32
  index_name 'questions_and_answers'
33
33
 
34
- mapping _parent: { type: 'question', required: true } do
34
+ mapping _parent: { type: 'question' }, _routing: { required: true } do
35
35
  indexes :text
36
36
  indexes :author
37
37
  end
@@ -29,13 +29,12 @@ module Elasticsearch
29
29
  indexes :authors do
30
30
  indexes :first_name
31
31
  indexes :last_name
32
- indexes :full_name, type: 'multi_field' do
33
- indexes :full_name
34
- indexes :raw, analyzer: 'keyword'
32
+ indexes :full_name, type: 'text' do
33
+ indexes :raw, type: 'keyword'
35
34
  end
36
35
  end
37
36
 
38
- indexes :categories, analyzer: 'keyword'
37
+ indexes :categories, type: 'keyword'
39
38
 
40
39
  indexes :comments, type: 'nested' do
41
40
  indexes :text
@@ -188,8 +187,8 @@ module Elasticsearch
188
187
  Post.__elasticsearch__.refresh_index!
189
188
 
190
189
  query = { query: {
191
- filtered: {
192
- query: {
190
+ bool: {
191
+ must: {
193
192
  multi_match: {
194
193
  fields: ['title'],
195
194
  query: 'first'
@@ -18,8 +18,8 @@ module Elasticsearch
18
18
 
19
19
  settings index: { number_of_shards: 1, number_of_replicas: 0 } do
20
20
  mapping do
21
- indexes :title, type: 'string', analyzer: 'snowball'
22
- indexes :body, type: 'string'
21
+ indexes :title, type: 'text', analyzer: 'snowball'
22
+ indexes :body, type: 'text'
23
23
  indexes :clicks, type: 'integer'
24
24
  indexes :created_at, type: 'date'
25
25
  end
@@ -16,7 +16,7 @@ module Elasticsearch
16
16
  scope :popular, -> { where('views >= 50') }
17
17
 
18
18
  mapping do
19
- indexes :title, type: 'string'
19
+ indexes :title, type: 'text'
20
20
  indexes :views, type: 'integer'
21
21
  indexes :numeric, type: 'integer'
22
22
  indexes :created_at, type: 'date'
@@ -16,7 +16,7 @@ module Elasticsearch
16
16
 
17
17
  settings index: { number_of_shards: 1, number_of_replicas: 0 } do
18
18
  mapping do
19
- indexes :title, type: 'string', analyzer: 'snowball'
19
+ indexes :title, type: 'text', analyzer: 'snowball'
20
20
  indexes :created_at, type: 'date'
21
21
  end
22
22
  end
@@ -20,7 +20,7 @@ if Mongo.available?
20
20
 
21
21
  settings index: { number_of_shards: 1, number_of_replicas: 0 } do
22
22
  mapping do
23
- indexes :title, type: 'string', analyzer: 'snowball'
23
+ indexes :title, type: 'text', analyzer: 'snowball'
24
24
  indexes :created_at, type: 'date'
25
25
  end
26
26
  end
@@ -20,7 +20,7 @@ module Elasticsearch
20
20
 
21
21
  settings index: {number_of_shards: 1, number_of_replicas: 0} do
22
22
  mapping do
23
- indexes :name, type: 'string', analyzer: 'snowball'
23
+ indexes :name, type: 'text', analyzer: 'snowball'
24
24
  indexes :created_at, type: 'date'
25
25
  end
26
26
  end
@@ -130,7 +130,7 @@ module Elasticsearch
130
130
 
131
131
  settings index: {number_of_shards: 1, number_of_replicas: 0} do
132
132
  mapping do
133
- indexes :name, type: 'string', analyzer: 'snowball'
133
+ indexes :name, type: 'text', analyzer: 'snowball'
134
134
  indexes :created_at, type: 'date'
135
135
  end
136
136
  end
@@ -0,0 +1,13 @@
1
+ require 'test_helper'
2
+
3
+ require 'hashie/version'
4
+
5
+ class Elasticsearch::Model::HashWrapperTest < Test::Unit::TestCase
6
+ context "The HashWrapper class" do
7
+ should "not print the warning for re-defined methods" do
8
+ Hashie.logger.expects(:warn).never
9
+
10
+ subject = Elasticsearch::Model::HashWrapper.new(:foo => 'bar', :sort => true)
11
+ end if Hashie::VERSION >= '3.5.3'
12
+ end
13
+ end
@@ -83,33 +83,23 @@ class Elasticsearch::Model::IndexingTest < Test::Unit::TestCase
83
83
  assert_equal 'boolean', mappings.to_hash[:mytype][:properties][:foo][:type]
84
84
  end
85
85
 
86
- should "define type as string by default" do
86
+ should "define type as 'text' by default" do
87
87
  mappings = Elasticsearch::Model::Indexing::Mappings.new :mytype
88
88
 
89
- mappings.indexes :bar, {}
90
- assert_equal 'string', mappings.to_hash[:mytype][:properties][:bar][:type]
89
+ mappings.indexes :bar
90
+ assert_equal 'text', mappings.to_hash[:mytype][:properties][:bar][:type]
91
91
  end
92
92
 
93
93
  should "define multiple fields" do
94
94
  mappings = Elasticsearch::Model::Indexing::Mappings.new :mytype
95
95
 
96
- mappings.indexes :foo_1, type: 'string' do
97
- indexes :raw, analyzer: 'keyword'
96
+ mappings.indexes :my_field, type: 'text' do
97
+ indexes :raw, type: 'keyword'
98
98
  end
99
99
 
100
- mappings.indexes :foo_2, type: 'multi_field' do
101
- indexes :raw, analyzer: 'keyword'
102
- end
103
-
104
- assert_equal 'string', mappings.to_hash[:mytype][:properties][:foo_1][:type]
105
- assert_equal 'string', mappings.to_hash[:mytype][:properties][:foo_1][:fields][:raw][:type]
106
- assert_equal 'keyword', mappings.to_hash[:mytype][:properties][:foo_1][:fields][:raw][:analyzer]
107
- assert_nil mappings.to_hash[:mytype][:properties][:foo_1][:properties]
108
-
109
- assert_equal 'multi_field', mappings.to_hash[:mytype][:properties][:foo_2][:type]
110
- assert_equal 'string', mappings.to_hash[:mytype][:properties][:foo_2][:fields][:raw][:type]
111
- assert_equal 'keyword', mappings.to_hash[:mytype][:properties][:foo_2][:fields][:raw][:analyzer]
112
- assert_nil mappings.to_hash[:mytype][:properties][:foo_2][:properties]
100
+ assert_equal 'text', mappings.to_hash[:mytype][:properties][:my_field][:type]
101
+ assert_equal 'keyword', mappings.to_hash[:mytype][:properties][:my_field][:fields][:raw][:type]
102
+ assert_nil mappings.to_hash[:mytype][:properties][:my_field][:properties]
113
103
  end
114
104
 
115
105
  should "define embedded properties" do
@@ -134,15 +124,15 @@ class Elasticsearch::Model::IndexingTest < Test::Unit::TestCase
134
124
  # Object is the default when `type` is missing and there's a block passed
135
125
  #
136
126
  assert_equal 'object', mappings.to_hash[:mytype][:properties][:foo][:type]
137
- assert_equal 'string', mappings.to_hash[:mytype][:properties][:foo][:properties][:bar][:type]
127
+ assert_equal 'text', mappings.to_hash[:mytype][:properties][:foo][:properties][:bar][:type]
138
128
  assert_nil mappings.to_hash[:mytype][:properties][:foo][:fields]
139
129
 
140
130
  assert_equal 'object', mappings.to_hash[:mytype][:properties][:foo_object][:type]
141
- assert_equal 'string', mappings.to_hash[:mytype][:properties][:foo_object][:properties][:bar][:type]
131
+ assert_equal 'text', mappings.to_hash[:mytype][:properties][:foo_object][:properties][:bar][:type]
142
132
  assert_nil mappings.to_hash[:mytype][:properties][:foo_object][:fields]
143
133
 
144
134
  assert_equal 'nested', mappings.to_hash[:mytype][:properties][:foo_nested][:type]
145
- assert_equal 'string', mappings.to_hash[:mytype][:properties][:foo_nested][:properties][:bar][:type]
135
+ assert_equal 'text', mappings.to_hash[:mytype][:properties][:foo_nested][:properties][:bar][:type]
146
136
  assert_nil mappings.to_hash[:mytype][:properties][:foo_nested][:fields]
147
137
 
148
138
  assert_equal :nested, mappings.to_hash[:mytype][:properties][:foo_nested_as_symbol][:type]
@@ -538,6 +528,27 @@ class Elasticsearch::Model::IndexingTest < Test::Unit::TestCase
538
528
  assert_nothing_raised { DummyIndexingModelForRecreate.create_index! }
539
529
  end
540
530
 
531
+ should "get the index settings and mappings from options" do
532
+ client = stub('client')
533
+ indices = stub('indices')
534
+ client.stubs(:indices).returns(indices)
535
+
536
+ indices.expects(:create).with do |payload|
537
+ assert_equal 'foobar', payload[:index]
538
+ assert_equal 3, payload[:body][:settings][:index][:number_of_shards]
539
+ assert_equal 'bar', payload[:body][:mappings][:foobar][:properties][:foo][:analyzer]
540
+ true
541
+ end.returns({})
542
+
543
+ DummyIndexingModelForRecreate.expects(:index_exists?).returns(false)
544
+ DummyIndexingModelForRecreate.expects(:client).returns(client).at_least_once
545
+
546
+ DummyIndexingModelForRecreate.create_index! \
547
+ index: 'foobar',
548
+ settings: { index: { number_of_shards: 3 } },
549
+ mappings: { foobar: { properties: { foo: { analyzer: 'bar' } } } }
550
+ end
551
+
541
552
  should "not create the index when it exists" do
542
553
  client = stub('client')
543
554
  indices = stub('indices')
@@ -27,7 +27,7 @@ class Elasticsearch::Model::ResponseTest < Test::Unit::TestCase
27
27
  assert_equal 'OK', response.shards.one
28
28
  end
29
29
 
30
- should "wrap the raw Hash response in Hashie::Mash" do
30
+ should "wrap the raw Hash response in a HashWrapper" do
31
31
  @search = Elasticsearch::Model::Searching::SearchRequest.new OriginClass, '*'
32
32
  @search.stubs(:execute!).returns({'hits' => { 'hits' => [] }, 'aggregations' => { 'dates' => 'FOO' }})
33
33
 
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elasticsearch-model
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Karel Minarik
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-04 00:00:00.000000000 Z
11
+ date: 2017-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: elasticsearch
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">"
18
18
  - !ruby/object:Gem::Version
19
- version: '2'
19
+ version: '1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">"
25
25
  - !ruby/object:Gem::Version
26
- version: '2'
26
+ version: '1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -337,6 +337,7 @@ files:
337
337
  - examples/activerecord_article.rb
338
338
  - examples/activerecord_associations.rb
339
339
  - examples/activerecord_mapping_completion.rb
340
+ - examples/activerecord_mapping_edge_ngram.rb
340
341
  - examples/couchbase_article.rb
341
342
  - examples/datamapper_article.rb
342
343
  - examples/mongoid_article.rb
@@ -354,6 +355,7 @@ files:
354
355
  - lib/elasticsearch/model/callbacks.rb
355
356
  - lib/elasticsearch/model/client.rb
356
357
  - lib/elasticsearch/model/ext/active_record.rb
358
+ - lib/elasticsearch/model/hash_wrapper.rb
357
359
  - lib/elasticsearch/model/importing.rb
358
360
  - lib/elasticsearch/model/indexing.rb
359
361
  - lib/elasticsearch/model/multimodel.rb
@@ -370,7 +372,7 @@ files:
370
372
  - lib/elasticsearch/model/searching.rb
371
373
  - lib/elasticsearch/model/serializing.rb
372
374
  - lib/elasticsearch/model/version.rb
373
- - test/integration/active_record_associations_parent_child.rb
375
+ - test/integration/active_record_associations_parent_child_test.rb
374
376
  - test/integration/active_record_associations_test.rb
375
377
  - test/integration/active_record_basic_test.rb
376
378
  - test/integration/active_record_custom_serialization_test.rb
@@ -390,6 +392,7 @@ files:
390
392
  - test/unit/adapter_test.rb
391
393
  - test/unit/callbacks_test.rb
392
394
  - test/unit/client_test.rb
395
+ - test/unit/hash_wrapper_test.rb
393
396
  - test/unit/importing_test.rb
394
397
  - test/unit/indexing_test.rb
395
398
  - test/unit/module_test.rb
@@ -434,7 +437,7 @@ signing_key:
434
437
  specification_version: 4
435
438
  summary: ActiveModel/Record integrations for Elasticsearch.
436
439
  test_files:
437
- - test/integration/active_record_associations_parent_child.rb
440
+ - test/integration/active_record_associations_parent_child_test.rb
438
441
  - test/integration/active_record_associations_test.rb
439
442
  - test/integration/active_record_basic_test.rb
440
443
  - test/integration/active_record_custom_serialization_test.rb
@@ -454,6 +457,7 @@ test_files:
454
457
  - test/unit/adapter_test.rb
455
458
  - test/unit/callbacks_test.rb
456
459
  - test/unit/client_test.rb
460
+ - test/unit/hash_wrapper_test.rb
457
461
  - test/unit/importing_test.rb
458
462
  - test/unit/indexing_test.rb
459
463
  - test/unit/module_test.rb