elasticsearch-model 2.0.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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