mongoid-elasticsearch 0.2.1 → 0.3.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: 227f98096d3f8725368150c8a275001d4b308fe8
4
- data.tar.gz: 5385ffd8dd90ca8397731a1ab73f0f63cda66a59
3
+ metadata.gz: 817468060649097bdc9d2087961b3c1e48a3f3bf
4
+ data.tar.gz: 11a922cfb895f5d0876148f98f69582ed267209a
5
5
  SHA512:
6
- metadata.gz: 86ae14cde369b32a520d6502af4a33b717f357c22cc7eaaf4c5cf2d585c93371dd38522588f447360f3ee3463b89da9264cebcea41531fe892de953793c7564a
7
- data.tar.gz: 696b7ba51d63adf247a37b5cd633985b2303a5914c838c0509f003197346d94eabc5933dd7ac64560610637aa5e1ba6ef1f834d775686dcc04e53a8f3d8b3641
6
+ metadata.gz: 8108f386fc0005c154d79cc7cf0b9e91d40545295880240781e62b9ec6a58f81e08d73fdfa7eabeaf19e6ed7418e7406f3971deee9d3b08c3bf9b655b4c4b972
7
+ data.tar.gz: 6c2cd84050776f09459cddb15c11526c13a55ed6f1719dba9183e869eed87f9e283de44c490ce9fcab9a3380e24585c5a572dd4272c4d7d19e08067dbea6cecc
data/.travis.yml CHANGED
@@ -10,10 +10,16 @@ rvm:
10
10
  - 1.9.3
11
11
  - 2.0.0
12
12
  - jruby-19mode
13
- # mongoid 4 has problems
14
- #- rbx-19mode
13
+ - ruby-head
15
14
 
16
15
  gemfile:
17
16
  - Gemfile
18
17
  - gemfiles/mongoid-4.0.gemfile
18
+ - gemfiles/es-git.gemfile
19
+ - gemfiles/es-0.4.0.gemfile
20
+ - gemfiles/es-0.4.1.gemfile
19
21
 
22
+ matrix:
23
+ allow_failures:
24
+ - rvm: ruby-head
25
+
data/README.md CHANGED
@@ -29,11 +29,12 @@ This gem is very simple and does not try hide any part of the ES REST api, it
29
29
  a model instance, ES 0.90.3 new completion suggester, etc (new features coming
30
30
  soon)
31
31
 
32
- ## Why use it (alternatives list):
32
+ ## Alternatives list:
33
33
 
34
- - [(re)Tire](https://github.com/karmi/retire) - retired
35
- - [RubberBand](https://github.com/grantr/rubberband) - EOL
36
- - [Elasticsearch gem](https://github.com/elasticsearch/elasticsearch-ruby) - too low-level and complex
34
+ - [Elasticsearch gem](https://github.com/elasticsearch/elasticsearch-ruby) - low-level and hard for simple use-cases
35
+ - [(re)Tire](https://github.com/karmi/retire)
36
+ - [RubberBand](https://github.com/grantr/rubberband) - EOL, no Mongoid
37
+ - [Mebla](https://github.com/cousine/mebla) - long dead
37
38
 
38
39
  ## Installation
39
40
 
@@ -60,7 +61,7 @@ Or install it yourself as:
60
61
  end
61
62
 
62
63
  Post.es.search 'test text' # shortcut for Post.es.search({q: 'test text'})
63
- result = Post.es.search query: {...}, facets: {...} etc
64
+ result = Post.es.search body: {query: {...}, facets: {...}} etc
64
65
  result.raw_response
65
66
  result.results # by default returns an Enumerable with Post instances exactly
66
67
  # like they were loaded from MongoDB
@@ -77,26 +78,50 @@ Or install it yourself as:
77
78
  response = Mongoid::Elasticsearch.search 'test'
78
79
 
79
80
 
81
+ search syntax docs: http://rubydoc.info/gems/elasticsearch-api/Elasticsearch/API/Actions#search-instance_method
82
+
80
83
  more docs: http://rubydoc.info/gems/elasticsearch-api/Elasticsearch/API/Actions
81
84
 
82
85
  ES docs: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/index.html
83
86
 
84
87
  ### Advanced:
85
88
 
89
+ prefix all app's index names:
90
+
91
+ Mongoid::Elasticsearch.prefix = 'my_app'
92
+
93
+ default options for Elasticsearch::Client.new (url etc)
94
+
95
+ Mongoid::Elasticsearch.client_options = {hosts: ['localhost']}
96
+
97
+ index definition options and custom model serialization:
98
+
86
99
  include Mongoid::Elasticsearch
87
- # define index_options (raw elasticsearch index definition
88
- #
89
- elasticsearch! index_name: 'mongoid_es_news', prefix_name: false, index_options: {}, index_mappings: {
90
- name: {
91
- type: 'multi_field',
92
- fields: {
93
- name: {type: 'string', analyzer: 'snowball'},
94
- raw: {type: 'string', index: :not_analyzed},
95
- suggest: {type: 'completion'}
96
- }
100
+ elasticsearch!({
101
+ # index name (prefix is added)
102
+ index_name: 'mongoid_es_news',
103
+
104
+ # don't use global name prefix
105
+ prefix_name: false,
106
+
107
+ # elasticsearch index definition
108
+ index_options: {},
109
+
110
+ # or only mappings with empty options
111
+ index_mappings: {
112
+ name: {
113
+ type: 'multi_field',
114
+ fields: {
115
+ name: {type: 'string', analyzer: 'snowball'},
116
+ raw: {type: 'string', index: :not_analyzed},
117
+ suggest: {type: 'completion'}
118
+ }
119
+ },
120
+ tags: {type: 'string', include_in_all: false}
97
121
  },
98
- tags: {type: 'string', include_in_all: false}
99
- }, wrapper: :load
122
+ wrapper: :load
123
+ })
124
+
100
125
  # customize what gets sent to elasticsearch:
101
126
  def as_indexed_json
102
127
  # id field is properly added automatically
@@ -106,6 +131,15 @@ ES docs: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/i
106
131
  }
107
132
  end
108
133
 
134
+ [Mapping definition docs](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-core-types.html)
135
+
136
+ ### Possible wrappers for results:
137
+
138
+ - :hash - raw hash from ES
139
+ - :mash - [Hashie::Mash](https://github.com/intridea/hashie#mash) (gem '[hashie](https://github.com/intridea/hashie)' must be added to gemfile)
140
+ - :load - load each found model by ID from database
141
+ - :model - create a model instance from data stored in elasticsearch
142
+
109
143
  See more examples in specs.
110
144
 
111
145
  ## Contributing
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "mongoid", github: "mongoid/mongoid", branch: "master"
4
+ gem 'elasticsearch', '0.4.0'
5
+
6
+ gemspec path: "../"
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "mongoid", github: "mongoid/mongoid", branch: "master"
4
+ gem 'elasticsearch', '0.4.1'
5
+
6
+ gemspec path: "../"
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "mongoid", github: "mongoid/mongoid", branch: "master"
4
+ gem 'elasticsearch', github: 'elasticsearch/elasticsearch-ruby', branch: "master"
5
+
6
+ gemspec path: "../"
@@ -29,27 +29,29 @@ module Mongoid
29
29
  query[:size] = ( per_page.to_i ) if per_page
30
30
  query[:from] = ( page.to_i <= 1 ? 0 : (per_page.to_i * (page.to_i-1)) ) if page && per_page
31
31
 
32
- Response.new(client, query.merge(type_options(true)), false, klass, klass.es_wrapper, options)
32
+ options[:wrapper] ||= klass.es_wrapper
33
+
34
+ Response.new(client, query.merge(type_options), false, klass, options)
33
35
  end
34
36
 
35
- def options_for(obj, escape = false)
36
- {id: obj.id.to_s}.merge type_options(escape)
37
+ def all(options = {})
38
+ search({body: {query: {match_all: {}}}}, options)
37
39
  end
38
40
 
39
- def type_options(escape = false)
40
- {index: index.name, type: escape ? Utils.escape(index.type) : index.type}
41
+ def options_for(obj)
42
+ {id: obj.id.to_s}.merge type_options
41
43
  end
42
44
 
43
- def index_item(obj)
44
- client.index({body: obj.as_indexed_json}.merge(options_for(obj, true)))
45
+ def type_options
46
+ {index: index.name, type: index.type}
45
47
  end
46
48
 
47
- def remove_item(obj)
48
- client.delete(options_for(obj, true).merge(ignore: 404))
49
+ def index_item(obj)
50
+ client.index({body: obj.as_indexed_json}.merge(options_for(obj)))
49
51
  end
50
52
 
51
- def all(options = {})
52
- search({match_all: {}}, options)
53
+ def remove_item(obj)
54
+ client.delete(options_for(obj).merge(ignore: 404))
53
55
  end
54
56
 
55
57
  def completion_supported?
@@ -14,7 +14,7 @@ module Mongoid
14
14
  end
15
15
 
16
16
  def type
17
- klass.model_name.collection
17
+ klass.model_name.collection.singularize
18
18
  end
19
19
 
20
20
  def options
@@ -11,12 +11,12 @@ module Mongoid
11
11
  attr_reader :time, :total, :options, :facets, :max
12
12
  attr_reader :response
13
13
 
14
- def initialize(client, query, multi, model, wrapper, options)
14
+ def initialize(client, query, multi, model, options)
15
15
  @client = client
16
16
  @query = query
17
17
  @multi = multi
18
18
  @model = model
19
- @wrapper = wrapper
19
+ @wrapper = options[:wrapper]
20
20
  @options = options
21
21
  end
22
22
 
@@ -44,7 +44,7 @@ module Mongoid
44
44
  end
45
45
 
46
46
  def hits
47
- @hits ||= raw_response['hits']['hits'].map { |d| d.update '_type' => Utils.unescape(d['_type']) }
47
+ @hits ||= raw_response['hits']['hits']
48
48
  end
49
49
 
50
50
  def results
@@ -59,7 +59,8 @@ module Mongoid
59
59
  end
60
60
  when :mash
61
61
  hits.map do |h|
62
- m = Hashie::Mash.new(h)
62
+ s = h.delete('_source')
63
+ m = Hashie::Mash.new(h.merge(s))
63
64
  m.id = BSON::ObjectId.from_string(h['_id'])
64
65
  m._id = m.id
65
66
  m
@@ -7,7 +7,7 @@ module Elasticsearch
7
7
  module Utils
8
8
  alias_method :__pathify_without_slashes, :__pathify
9
9
  def __pathify(*segments)
10
- __pathify_without_slashes(*segments).gsub('%252F', '%2F')
10
+ __pathify_without_slashes(*segments.map { |s| s.gsub('/', '%2F')}).gsub('%252F', '%2F')
11
11
  end
12
12
  end
13
13
  end
@@ -4,16 +4,6 @@ require 'uri'
4
4
  module Mongoid
5
5
  module Elasticsearch
6
6
  module Utils
7
-
8
- def escape(s)
9
- URI.encode_www_form_component(s.to_s)
10
- end
11
-
12
- def unescape(s)
13
- s = s.to_s.respond_to?(:force_encoding) ? s.to_s.force_encoding(Encoding::UTF_8) : s.to_s
14
- URI.decode_www_form_component(s)
15
- end
16
-
17
7
  def clean(s)
18
8
  s.to_s.gsub(/\W+/, ' ').gsub(/ +/, '').strip
19
9
  end
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module Elasticsearch
3
- VERSION = "0.2.1"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
@@ -9,7 +9,10 @@ require 'mongoid/elasticsearch/callbacks'
9
9
  require 'mongoid/elasticsearch/index'
10
10
  require 'mongoid/elasticsearch/indexing'
11
11
  require 'mongoid/elasticsearch/response'
12
- require 'mongoid/elasticsearch/slash_monkeypatch'
12
+
13
+ if Elasticsearch::VERSION < '0.4.1'
14
+ require 'mongoid/elasticsearch/slash_monkeypatch'
15
+ end
13
16
 
14
17
  module Mongoid
15
18
  module Elasticsearch
@@ -81,7 +84,7 @@ module Mongoid
81
84
  end
82
85
 
83
86
  # search multiple models
84
- def self.search(query, options = {}, wrapper = :model)
87
+ def self.search(query, options = {})
85
88
  if query.is_a?(String)
86
89
  query = {q: Utils.clean(query)}
87
90
  end
@@ -98,9 +101,10 @@ module Mongoid
98
101
  query[:size] = ( per_page.to_i ) if per_page
99
102
  query[:from] = ( page.to_i <= 1 ? 0 : (per_page.to_i * (page.to_i-1)) ) if page && per_page
100
103
 
104
+ options[:wrapper] ||= :model
101
105
 
102
106
  client = ::Elasticsearch::Client.new Mongoid::Elasticsearch.client_options
103
- Response.new(client, query, true, nil, wrapper, options)
107
+ Response.new(client, query, true, nil, options)
104
108
  end
105
109
  end
106
110
  end
@@ -27,4 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "kaminari"
28
28
  spec.add_development_dependency "database_cleaner"
29
29
  spec.add_development_dependency "coveralls"
30
+ spec.add_development_dependency "hashie"
30
31
  end
@@ -4,7 +4,7 @@ describe Article do
4
4
  it 'properly uses options' do
5
5
  Article.es_index_name.should eq 'mongoid_es_news'
6
6
  Article.es.index.name.should eq 'mongoid_es_news'
7
- Article.es.index.type.should eq 'articles'
7
+ Article.es.index.type.should eq 'article'
8
8
  Article.es_wrapper.should eq :load
9
9
  Article.es_client_options.should eq({})
10
10
  end
@@ -210,13 +210,20 @@ describe "Multisearch" do
210
210
  response.to_a.map(&:class).map(&:name).uniq.sort.should eq ['Article', 'Namespaced::Model', 'Post']
211
211
  response.select { |r| r.class == Article && r.id == @article_1.id }.first.should_not be_nil
212
212
  end
213
+
214
+ it '#multi_with_load' do
215
+ response = Mongoid::Elasticsearch.search 'test', wrapper: :load
216
+ response.length.should eq 4
217
+ response.to_a.map(&:class).map(&:name).uniq.sort.should eq ['Article', 'Namespaced::Model', 'Post']
218
+ response.select { |r| r.class == Article && r.id == @article_1.id }.first.should_not be_nil
219
+ end
213
220
  end
214
221
 
215
222
  describe Namespaced::Model do
216
223
  it 'properly uses options' do
217
224
  Namespaced::Model.es_index_name.should eq 'mongoid_es_test_namespaced_models'
218
225
  Namespaced::Model.es.index.name.should eq 'mongoid_es_test_namespaced_models'
219
- Namespaced::Model.es.index.type.should eq 'namespaced/models'
226
+ Namespaced::Model.es.index.type.should eq 'namespaced/model'
220
227
  Namespaced::Model.es_wrapper.should eq :model
221
228
  Namespaced::Model.es_client_options.should eq({})
222
229
  end
@@ -265,28 +272,45 @@ describe Namespaced::Model do
265
272
 
266
273
  context 'pagination' do
267
274
  before :each do
275
+ Namespaced::Model.es.index.reset
268
276
  @articles = []
269
277
  20.times { @articles << Namespaced::Model.create!(name: 'test') }
278
+ @a1 = Namespaced::Model.create!(name: 'irrelevant')
279
+ @a2 = Namespaced::Model.create!(name: 'unmatched')
270
280
  Namespaced::Model.es.index.refresh
271
281
  end
272
282
 
283
+ it '#search ignores irrelevant' do
284
+ Namespaced::Model.es.search('irrelevant').to_a.size.should eq 1
285
+ Namespaced::Model.es.search('test').to_a.size.should eq 20
286
+ end
287
+
288
+ it '#search dynamic wrapper' do
289
+ Namespaced::Model.es.search('test', wrapper: :hash).map(&:class).map(&:name).uniq.should eq ['Hash']
290
+ Namespaced::Model.es.search('test', wrapper: :mash).map(&:class).map(&:name).uniq.should eq ['Hashie::Mash']
291
+ Namespaced::Model.es.search('test', wrapper: :mash).first.name.should eq 'test'
292
+ end
293
+
273
294
  it '#search' do
274
295
  Namespaced::Model.es.search('test', per_page: 10, page: 2).to_a.size.should eq 10
275
296
  Namespaced::Model.es.search('test', per_page: 30, page: 2).to_a.size.should eq 0
276
297
  Namespaced::Model.es.search('test', per_page: 2, page: 2).to_a.size.should eq 2
298
+ Namespaced::Model.es.search(body: {query: {query_string: {query: 'test'}}}).to_a.length.should eq 20
277
299
  end
278
300
 
279
301
  it '#all' do
280
302
  result = Namespaced::Model.es.all(per_page: 7, page: 3)
281
- result.num_pages.should eq 3
282
- result.to_a.size.should eq 6
303
+ result.num_pages.should eq 4
304
+ result.to_a.size.should eq 7
283
305
  p1 = Namespaced::Model.es.all(per_page: 7, page: 1).to_a
284
306
  p2 = Namespaced::Model.es.all(per_page: 7, page: 2).to_a
307
+ p4 = Namespaced::Model.es.all(per_page: 7, page: 4).to_a
285
308
  p1.length.should eq 7
286
309
  p2.length.should eq 7
287
- all = (result.to_a + p1 + p2).map(&:id).map(&:to_s).sort
288
- all.length.should eq 20
289
- all.should eq @articles.map(&:id).map(&:to_s).sort
310
+ p4.length.should eq 1
311
+ all = (p1 + p2 + result.to_a + p4).map(&:id).map(&:to_s).sort
312
+ all.length.should eq 22
313
+ all.should eq (@articles + [@a1, @a2]).map(&:id).map(&:to_s).sort
290
314
  end
291
315
  end
292
316
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,11 @@
1
+ require 'simplecov'
1
2
  require 'coveralls'
2
- Coveralls.wear!
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ Coveralls::SimpleCov::Formatter
7
+ ]
8
+ SimpleCov.start
3
9
 
4
10
  $LOAD_PATH.unshift(File.dirname(__FILE__))
5
11
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
@@ -9,6 +15,7 @@ MODELS = File.join(File.dirname(__FILE__), "models")
9
15
  require "rubygems"
10
16
  require "rspec"
11
17
  require "mongoid"
18
+ require "hashie"
12
19
  require "database_cleaner"
13
20
 
14
21
  require "mongoid-elasticsearch"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - glebtv
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-18 00:00:00.000000000 Z
11
+ date: 2013-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mongoid
@@ -128,6 +128,20 @@ dependencies:
128
128
  - - '>='
129
129
  - !ruby/object:Gem::Version
130
130
  version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: hashie
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - '>='
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
131
145
  description: Simple and easy integration of mongoid with the new elasticsearch gem
132
146
  email:
133
147
  - glebtv@gmail.com
@@ -145,6 +159,9 @@ files:
145
159
  - MIT-LICENSE.txt
146
160
  - README.md
147
161
  - Rakefile
162
+ - gemfiles/es-0.4.0.gemfile
163
+ - gemfiles/es-0.4.1.gemfile
164
+ - gemfiles/es-git.gemfile
148
165
  - gemfiles/mongoid-4.0.gemfile
149
166
  - lib/mongoid-elasticsearch.rb
150
167
  - lib/mongoid/elasticsearch.rb