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 +4 -4
- data/README.md +5 -1
- data/elasticsearch-model.gemspec +1 -1
- data/examples/activerecord_associations.rb +46 -11
- data/examples/activerecord_mapping_completion.rb +24 -9
- data/examples/activerecord_mapping_edge_ngram.rb +101 -0
- data/lib/elasticsearch/model.rb +4 -3
- data/lib/elasticsearch/model/hash_wrapper.rb +15 -0
- data/lib/elasticsearch/model/indexing.rb +9 -5
- data/lib/elasticsearch/model/response.rb +2 -2
- data/lib/elasticsearch/model/response/aggregations.rb +2 -0
- data/lib/elasticsearch/model/response/result.rb +1 -1
- data/lib/elasticsearch/model/response/suggestions.rb +2 -0
- data/lib/elasticsearch/model/version.rb +1 -1
- data/test/integration/{active_record_associations_parent_child.rb → active_record_associations_parent_child_test.rb} +1 -1
- data/test/integration/active_record_associations_test.rb +5 -6
- data/test/integration/active_record_basic_test.rb +2 -2
- data/test/integration/active_record_import_test.rb +1 -1
- data/test/integration/active_record_pagination_test.rb +1 -1
- data/test/integration/mongoid_basic_test.rb +1 -1
- data/test/integration/multiple_models_test.rb +2 -2
- data/test/unit/hash_wrapper_test.rb +13 -0
- data/test/unit/indexing_test.rb +32 -21
- data/test/unit/response_test.rb +1 -1
- metadata +12 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 578a444488ef68a50e4f19c87bf43c3c3d950a39
|
4
|
+
data.tar.gz: c602b0f07801e4dc864921a067a94a8fc482da75
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
data/elasticsearch-model.gemspec
CHANGED
@@ -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[
|
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
|
-
|
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 "
|
172
|
+
puts "",
|
173
|
+
"All Models containing 'one':".ansi(:bold),
|
174
|
+
Elasticsearch::Model.search('one').records.to_a.map(&:inspect),
|
175
|
+
""
|
167
176
|
|
168
|
-
#
|
177
|
+
# Difference between `records` and `results`
|
169
178
|
#
|
170
|
-
|
179
|
+
response = Article.search query: { match: { title: 'first' } }
|
171
180
|
|
172
|
-
|
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
|
-
|
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(
|
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
|
-
|
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
|
-
|
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: '
|
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['
|
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;
|
data/lib/elasticsearch/model.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
-
require '
|
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 `
|
69
|
-
@mapping[name][:type] ||= '
|
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
|
-
|
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:
|
231
|
-
mappings:
|
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
|
-
|
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
|
-
|
66
|
+
HashWrapper.new(response['_shards'])
|
67
67
|
end
|
68
68
|
|
69
69
|
# Returns a Hashie::Mash of the aggregations
|
@@ -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: '
|
33
|
-
indexes :
|
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,
|
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
|
-
|
192
|
-
|
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: '
|
22
|
-
indexes :body, type: '
|
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
|
|
17
17
|
settings index: { number_of_shards: 1, number_of_replicas: 0 } do
|
18
18
|
mapping do
|
19
|
-
indexes :title, type: '
|
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: '
|
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: '
|
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: '
|
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
|
data/test/unit/indexing_test.rb
CHANGED
@@ -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
|
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 '
|
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 :
|
97
|
-
indexes :raw,
|
96
|
+
mappings.indexes :my_field, type: 'text' do
|
97
|
+
indexes :raw, type: 'keyword'
|
98
98
|
end
|
99
99
|
|
100
|
-
mappings.
|
101
|
-
|
102
|
-
|
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 '
|
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 '
|
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 '
|
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')
|
data/test/unit/response_test.rb
CHANGED
@@ -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
|
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:
|
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-
|
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: '
|
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: '
|
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/
|
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/
|
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
|