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 +4 -4
- data/.travis.yml +8 -2
- data/README.md +51 -17
- data/gemfiles/es-0.4.0.gemfile +6 -0
- data/gemfiles/es-0.4.1.gemfile +6 -0
- data/gemfiles/es-git.gemfile +6 -0
- data/lib/mongoid/elasticsearch/es.rb +13 -11
- data/lib/mongoid/elasticsearch/index.rb +1 -1
- data/lib/mongoid/elasticsearch/response.rb +5 -4
- data/lib/mongoid/elasticsearch/slash_monkeypatch.rb +1 -1
- data/lib/mongoid/elasticsearch/utils.rb +0 -10
- data/lib/mongoid/elasticsearch/version.rb +1 -1
- data/lib/mongoid/elasticsearch.rb +7 -3
- data/mongoid-elasticsearch.gemspec +1 -0
- data/spec/mongoid_elasticsearch_spec.rb +31 -7
- data/spec/spec_helper.rb +8 -1
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 817468060649097bdc9d2087961b3c1e48a3f3bf
|
4
|
+
data.tar.gz: 11a922cfb895f5d0876148f98f69582ed267209a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
##
|
32
|
+
## Alternatives list:
|
33
33
|
|
34
|
-
- [
|
35
|
-
- [
|
36
|
-
- [
|
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
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
99
|
-
}
|
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
|
@@ -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
|
-
|
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
|
36
|
-
{
|
37
|
+
def all(options = {})
|
38
|
+
search({body: {query: {match_all: {}}}}, options)
|
37
39
|
end
|
38
40
|
|
39
|
-
def
|
40
|
-
{
|
41
|
+
def options_for(obj)
|
42
|
+
{id: obj.id.to_s}.merge type_options
|
41
43
|
end
|
42
44
|
|
43
|
-
def
|
44
|
-
|
45
|
+
def type_options
|
46
|
+
{index: index.name, type: index.type}
|
45
47
|
end
|
46
48
|
|
47
|
-
def
|
48
|
-
client.
|
49
|
+
def index_item(obj)
|
50
|
+
client.index({body: obj.as_indexed_json}.merge(options_for(obj)))
|
49
51
|
end
|
50
52
|
|
51
|
-
def
|
52
|
-
|
53
|
+
def remove_item(obj)
|
54
|
+
client.delete(options_for(obj).merge(ignore: 404))
|
53
55
|
end
|
54
56
|
|
55
57
|
def completion_supported?
|
@@ -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,
|
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']
|
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
|
-
|
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
|
@@ -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
|
-
|
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 = {}
|
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,
|
107
|
+
Response.new(client, query, true, nil, options)
|
104
108
|
end
|
105
109
|
end
|
106
110
|
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 '
|
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/
|
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
|
282
|
-
result.to_a.size.should eq
|
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
|
-
|
288
|
-
all.
|
289
|
-
all.should eq
|
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
|
-
|
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.
|
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-
|
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
|