wj-mongoid-elasticsearch 0.0.1
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 +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +16 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +14 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +149 -0
- data/MIT-LICENSE.txt +22 -0
- data/README.md +258 -0
- data/Rakefile +9 -0
- data/lib/mongoid/elasticsearch/callbacks.rb +40 -0
- data/lib/mongoid/elasticsearch/es.rb +111 -0
- data/lib/mongoid/elasticsearch/index.rb +62 -0
- data/lib/mongoid/elasticsearch/indexing.rb +25 -0
- data/lib/mongoid/elasticsearch/monkeypatches.rb +56 -0
- data/lib/mongoid/elasticsearch/pagination.rb +63 -0
- data/lib/mongoid/elasticsearch/railtie.rb +11 -0
- data/lib/mongoid/elasticsearch/response.rb +193 -0
- data/lib/mongoid/elasticsearch/tasks.rb +28 -0
- data/lib/mongoid/elasticsearch/utils.rb +15 -0
- data/lib/mongoid/elasticsearch/version.rb +5 -0
- data/lib/mongoid/elasticsearch.rb +129 -0
- data/lib/mongoid-elasticsearch.rb +1 -0
- data/mongoid-elasticsearch.gemspec +34 -0
- data/spec/models/article.rb +32 -0
- data/spec/models/namespaced.rb +22 -0
- data/spec/models/no_autocreate.rb +9 -0
- data/spec/models/nowrapper.rb +9 -0
- data/spec/models/post.rb +20 -0
- data/spec/mongoid_elasticsearch_spec.rb +454 -0
- data/spec/spec_helper.rb +76 -0
- metadata +258 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e3d100f567a331d026d6f11af5855250a175d000
|
4
|
+
data.tar.gz: 19941f55187e0dfae9fe24939174b2d321d8ace4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aa17df21a93b08424b850ff8acc18be1242d0d3b8c34f646d1cce05d3521ff30708b815d4f21dacde93505c6155647aacdf849141e4cedc26af0193c9968200f
|
7
|
+
data.tar.gz: 9e2de6a5c3c73e9a17594c4134e04b23d999424240e81c7fc413d42d92a665bc39a741110326b8972ee954c5ea4eb6330e4bbeb34d37a3b5098ce6e3f0781eba
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
mongoid-elasticsearch
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.3
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
## 0.8.1 (March 4, 2014) ##
|
2
|
+
|
3
|
+
* New method "Model.without_es_update!" to temporally disable callbacks (ie, for testing) (by [@xronos-i-am](https://github.com/xronos-i-am))
|
4
|
+
|
5
|
+
## 0.8.0 (March 4, 2014) ##
|
6
|
+
|
7
|
+
* fix results with :load wrapper #6 (by [@xronos-i-am](https://github.com/xronos-i-am))
|
8
|
+
* Added option to prevent automatic creating of index. #7 (thx [@intrica](https://github.com/intrica))
|
9
|
+
* use after_initalize to create indexes later in the app boot process
|
10
|
+
|
11
|
+
Set Mongoid::Elasticsearch.autocreate_indexes to false in an initalizer to prevent automatic creation for all indexes.
|
12
|
+
|
13
|
+
You can always use ```rake es:create``` to create all indexes or call Mongoid::Elasticsearch.create_all_indexes!.
|
14
|
+
|
15
|
+
Indexes defined with skip_create: true are not created with all other indexes and must be created manually with Model.es.index.create
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/DatabaseCleaner/database_cleaner.git
|
3
|
+
revision: 49ca0f3e8ac4c096129442d0f942d39f2c0d7dde
|
4
|
+
specs:
|
5
|
+
database_cleaner (1.5.2)
|
6
|
+
|
7
|
+
PATH
|
8
|
+
remote: .
|
9
|
+
specs:
|
10
|
+
mongoid-elasticsearch (0.9.1)
|
11
|
+
elasticsearch (~> 1.0.13)
|
12
|
+
mongoid (>= 3.0, < 6.0)
|
13
|
+
ruby-progressbar
|
14
|
+
|
15
|
+
GEM
|
16
|
+
remote: https://rubygems.org/
|
17
|
+
specs:
|
18
|
+
actionpack (4.2.6)
|
19
|
+
actionview (= 4.2.6)
|
20
|
+
activesupport (= 4.2.6)
|
21
|
+
rack (~> 1.6)
|
22
|
+
rack-test (~> 0.6.2)
|
23
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
24
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
25
|
+
actionview (4.2.6)
|
26
|
+
activesupport (= 4.2.6)
|
27
|
+
builder (~> 3.1)
|
28
|
+
erubis (~> 2.7.0)
|
29
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
30
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
31
|
+
activemodel (4.2.6)
|
32
|
+
activesupport (= 4.2.6)
|
33
|
+
builder (~> 3.1)
|
34
|
+
activesupport (4.2.6)
|
35
|
+
i18n (~> 0.7)
|
36
|
+
json (~> 1.7, >= 1.7.7)
|
37
|
+
minitest (~> 5.1)
|
38
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
39
|
+
tzinfo (~> 1.1)
|
40
|
+
bson (4.1.0)
|
41
|
+
builder (3.2.2)
|
42
|
+
coveralls (0.8.13)
|
43
|
+
json (~> 1.8)
|
44
|
+
simplecov (~> 0.11.0)
|
45
|
+
term-ansicolor (~> 1.3)
|
46
|
+
thor (~> 0.19.1)
|
47
|
+
tins (~> 1.6.0)
|
48
|
+
diff-lcs (1.2.5)
|
49
|
+
docile (1.1.5)
|
50
|
+
elasticsearch (1.0.17)
|
51
|
+
elasticsearch-api (= 1.0.17)
|
52
|
+
elasticsearch-transport (= 1.0.17)
|
53
|
+
elasticsearch-api (1.0.17)
|
54
|
+
multi_json
|
55
|
+
elasticsearch-transport (1.0.17)
|
56
|
+
faraday
|
57
|
+
multi_json
|
58
|
+
erubis (2.7.0)
|
59
|
+
faraday (0.9.2)
|
60
|
+
multipart-post (>= 1.2, < 3)
|
61
|
+
glebtv-httpclient (3.2.8)
|
62
|
+
lru_redux
|
63
|
+
hashie (3.4.3)
|
64
|
+
i18n (0.7.0)
|
65
|
+
json (1.8.3)
|
66
|
+
kaminari (0.16.3)
|
67
|
+
actionpack (>= 3.0.0)
|
68
|
+
activesupport (>= 3.0.0)
|
69
|
+
loofah (2.0.3)
|
70
|
+
nokogiri (>= 1.5.9)
|
71
|
+
lru_redux (1.1.0)
|
72
|
+
mini_portile2 (2.0.0)
|
73
|
+
minitest (5.8.4)
|
74
|
+
mongo (2.2.4)
|
75
|
+
bson (~> 4.0)
|
76
|
+
mongoid (5.1.2)
|
77
|
+
activemodel (~> 4.0)
|
78
|
+
mongo (~> 2.1)
|
79
|
+
origin (~> 2.2)
|
80
|
+
tzinfo (>= 0.3.37)
|
81
|
+
mongoid-compatibility (0.3.1)
|
82
|
+
activesupport
|
83
|
+
mongoid (>= 2.0)
|
84
|
+
mongoid-slug (5.0.0)
|
85
|
+
mongoid (>= 3.0)
|
86
|
+
mongoid-compatibility
|
87
|
+
stringex (~> 2.0)
|
88
|
+
multi_json (1.11.2)
|
89
|
+
multipart-post (2.0.0)
|
90
|
+
nokogiri (1.6.7.2)
|
91
|
+
mini_portile2 (~> 2.0.0.rc2)
|
92
|
+
origin (2.2.0)
|
93
|
+
rack (1.6.4)
|
94
|
+
rack-test (0.6.3)
|
95
|
+
rack (>= 1.0)
|
96
|
+
rails-deprecated_sanitizer (1.0.3)
|
97
|
+
activesupport (>= 4.2.0.alpha)
|
98
|
+
rails-dom-testing (1.0.7)
|
99
|
+
activesupport (>= 4.2.0.beta, < 5.0)
|
100
|
+
nokogiri (~> 1.6.0)
|
101
|
+
rails-deprecated_sanitizer (>= 1.0.1)
|
102
|
+
rails-html-sanitizer (1.0.3)
|
103
|
+
loofah (~> 2.0)
|
104
|
+
rake (11.1.2)
|
105
|
+
rspec (3.4.0)
|
106
|
+
rspec-core (~> 3.4.0)
|
107
|
+
rspec-expectations (~> 3.4.0)
|
108
|
+
rspec-mocks (~> 3.4.0)
|
109
|
+
rspec-core (3.4.4)
|
110
|
+
rspec-support (~> 3.4.0)
|
111
|
+
rspec-expectations (3.4.0)
|
112
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
113
|
+
rspec-support (~> 3.4.0)
|
114
|
+
rspec-mocks (3.4.1)
|
115
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
116
|
+
rspec-support (~> 3.4.0)
|
117
|
+
rspec-support (3.4.1)
|
118
|
+
ruby-progressbar (1.7.5)
|
119
|
+
simplecov (0.11.2)
|
120
|
+
docile (~> 1.1.0)
|
121
|
+
json (~> 1.8)
|
122
|
+
simplecov-html (~> 0.10.0)
|
123
|
+
simplecov-html (0.10.0)
|
124
|
+
stringex (2.6.0)
|
125
|
+
term-ansicolor (1.3.2)
|
126
|
+
tins (~> 1.0)
|
127
|
+
thor (0.19.1)
|
128
|
+
thread_safe (0.3.5)
|
129
|
+
tins (1.6.0)
|
130
|
+
tzinfo (1.2.2)
|
131
|
+
thread_safe (~> 0.1)
|
132
|
+
|
133
|
+
PLATFORMS
|
134
|
+
ruby
|
135
|
+
|
136
|
+
DEPENDENCIES
|
137
|
+
bundler
|
138
|
+
coveralls
|
139
|
+
database_cleaner!
|
140
|
+
glebtv-httpclient
|
141
|
+
hashie
|
142
|
+
kaminari
|
143
|
+
mongoid-elasticsearch!
|
144
|
+
mongoid-slug (~> 5.0.0)
|
145
|
+
rake
|
146
|
+
rspec
|
147
|
+
|
148
|
+
BUNDLED WITH
|
149
|
+
1.11.2
|
data/MIT-LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 glebtv
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,258 @@
|
|
1
|
+
# Mongoid::Elasticsearch
|
2
|
+
|
3
|
+
[](https://travis-ci.org/rs-pro/mongoid-elasticsearch)
|
4
|
+
[](https://coveralls.io/r/rs-pro/mongoid-elasticsearch?branch=master)
|
5
|
+
[](http://badge.fury.io/rb/mongoid-elasticsearch)
|
6
|
+
[](https://www.versioneye.com/user/projects/53e73fe735080d1e4d00009c)
|
7
|
+
[](https://github.com/rs-pro/mongoid-elasticsearch/issues)
|
8
|
+
[](https://github.com/rs-pro/mongoid-elasticsearch/blob/master/MIT-LICENSE.txt)
|
9
|
+
|
10
|
+
|
11
|
+
Use [Elasticsearch](http://www.elasticsearch.org/) with mongoid with just a few
|
12
|
+
lines of code
|
13
|
+
|
14
|
+
Allows easy usage of [the new Elasticsearch gem](https://github.com/elasticsearch/elasticsearch-ruby)
|
15
|
+
with [Mongoid 4](https://github.com/mongoid/mongoid)
|
16
|
+
|
17
|
+
## Features
|
18
|
+
|
19
|
+
- Uses new elasticsearch gem
|
20
|
+
- Has a simple high-level API
|
21
|
+
- No weird undocumented DSL, just raw JSON for queries and index definitions
|
22
|
+
- Allows for full power of elasticsearch when it's necessary
|
23
|
+
- Indexes are automatically created if they don't exist on app boot
|
24
|
+
- Works out of the box with zero configuration
|
25
|
+
- Multi-model search with real model instances and pagination
|
26
|
+
- Whole test suite is run against a real ES instance, no mocks
|
27
|
+
|
28
|
+
This gem is very simple and does not try hide any part of the ES REST api, it
|
29
|
+
just adds some shortcuts for prefixing index names, automatic updating of the index
|
30
|
+
when models are added\changed, search with pagination, wrapping results in
|
31
|
+
a model instance, ES 0.90.3 new completion suggester, etc (new features coming
|
32
|
+
soon)
|
33
|
+
|
34
|
+
## Alternatives list:
|
35
|
+
|
36
|
+
- [Elasticsearch gem](https://github.com/elasticsearch/elasticsearch-ruby) - low-level and hard for simple use-cases
|
37
|
+
- [(re)Tire](https://github.com/karmi/retire)
|
38
|
+
- [RubberBand](https://github.com/grantr/rubberband) - EOL, no Mongoid
|
39
|
+
- [Mebla](https://github.com/cousine/mebla) - long dead
|
40
|
+
|
41
|
+
## Installation
|
42
|
+
|
43
|
+
Add this line to your application's Gemfile:
|
44
|
+
|
45
|
+
gem 'mongoid-elasticsearch'
|
46
|
+
|
47
|
+
And then execute:
|
48
|
+
|
49
|
+
$ bundle
|
50
|
+
|
51
|
+
Or install it yourself as:
|
52
|
+
|
53
|
+
$ gem install mongoid-elasticsearch
|
54
|
+
|
55
|
+
## Usage
|
56
|
+
|
57
|
+
### Basic:
|
58
|
+
|
59
|
+
class Post
|
60
|
+
include Mongoid::Document
|
61
|
+
include Mongoid::Elasticsearch
|
62
|
+
elasticsearch!
|
63
|
+
end
|
64
|
+
|
65
|
+
Post.es.search 'test text' # shortcut for Post.es.search({q: 'test text'})
|
66
|
+
result = Post.es.search body: {query: {...}, facets: {...}} etc
|
67
|
+
result.raw_response
|
68
|
+
result.results # by default returns an Enumerable with Post instances exactly
|
69
|
+
# like they were loaded from MongoDB
|
70
|
+
Post.es.index.create # create index (done automatically on app boot)
|
71
|
+
Post.es.index.delete # drop index
|
72
|
+
Post.es.index.reset # recreate index
|
73
|
+
Post.es.index.refresh # force index update (useful for specs)
|
74
|
+
Post.es.client # Elasticsearch::Client instance
|
75
|
+
|
76
|
+
### Completion:
|
77
|
+
|
78
|
+
include Mongoid::Elasticsearch
|
79
|
+
elasticsearch! index_mappings: {
|
80
|
+
name: {
|
81
|
+
type: 'multi_field',
|
82
|
+
fields: {
|
83
|
+
name: {type: 'string', boost: 10},
|
84
|
+
suggest: {type: 'completion'}
|
85
|
+
}
|
86
|
+
},
|
87
|
+
desc: {type: 'string'},
|
88
|
+
}
|
89
|
+
|
90
|
+
Post.es.completion('te', 'name.suggest') # requires ES 0.90.3
|
91
|
+
|
92
|
+
### Search multiple models:
|
93
|
+
|
94
|
+
# By default only searches in indexes managed by Mongoid::Elasticsearch
|
95
|
+
# to ignore other apps indexes in same ES instance
|
96
|
+
response = Mongoid::Elasticsearch.search 'test'
|
97
|
+
|
98
|
+
|
99
|
+
search syntax docs: http://rubydoc.info/gems/elasticsearch-api/Elasticsearch/API/Actions#search-instance_method
|
100
|
+
|
101
|
+
ES Actions docs: http://rubydoc.info/gems/elasticsearch-api/Elasticsearch/API/Actions
|
102
|
+
|
103
|
+
ES Indices docs: http://rubydoc.info/gems/elasticsearch-api/Elasticsearch/API/Indices/Actions
|
104
|
+
|
105
|
+
ES docs: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/index.html
|
106
|
+
|
107
|
+
### Advanced:
|
108
|
+
|
109
|
+
prefix all app's index names:
|
110
|
+
|
111
|
+
Mongoid::Elasticsearch.prefix = 'my_app'
|
112
|
+
|
113
|
+
default options for Elasticsearch::Client.new (url etc)
|
114
|
+
|
115
|
+
Mongoid::Elasticsearch.client_options = {hosts: ['localhost']}
|
116
|
+
|
117
|
+
index definition options and custom model serialization:
|
118
|
+
|
119
|
+
include Mongoid::Elasticsearch
|
120
|
+
elasticsearch!({
|
121
|
+
# index name (prefix is added)
|
122
|
+
index_name: 'mongoid_es_news',
|
123
|
+
|
124
|
+
# don't use global name prefix
|
125
|
+
prefix_name: false,
|
126
|
+
|
127
|
+
# elasticsearch index definition
|
128
|
+
index_options: {},
|
129
|
+
|
130
|
+
# or only mappings with empty options
|
131
|
+
index_mappings: {
|
132
|
+
name: {
|
133
|
+
type: 'multi_field',
|
134
|
+
fields: {
|
135
|
+
name: {type: 'string', analyzer: 'snowball'},
|
136
|
+
raw: {type: 'string', index: :not_analyzed},
|
137
|
+
suggest: {type: 'completion'}
|
138
|
+
}
|
139
|
+
},
|
140
|
+
tags: {type: 'string', include_in_all: false}
|
141
|
+
},
|
142
|
+
wrapper: :load
|
143
|
+
})
|
144
|
+
|
145
|
+
# customize what gets sent to elasticsearch:
|
146
|
+
def as_indexed_json
|
147
|
+
# id field is properly added automatically
|
148
|
+
{
|
149
|
+
name: name,
|
150
|
+
excerpt: excerpt
|
151
|
+
}
|
152
|
+
# mongoid_slug note: add _slugs to as_indexed_json, NOT slug
|
153
|
+
end
|
154
|
+
|
155
|
+
Example mapping with boost field:
|
156
|
+
|
157
|
+
elasticsearch!({
|
158
|
+
index_name: Rails.env.test? ? 'vv_test_articles' : 'vv_articles',
|
159
|
+
index_options: {
|
160
|
+
settings: {
|
161
|
+
index: {
|
162
|
+
analysis: {
|
163
|
+
analyzer: {
|
164
|
+
my_analyzer: {
|
165
|
+
type: "snowball",
|
166
|
+
language: "Russian"
|
167
|
+
}
|
168
|
+
}
|
169
|
+
}
|
170
|
+
}
|
171
|
+
},
|
172
|
+
mappings: {
|
173
|
+
"articles/article" => {
|
174
|
+
_boost: {name: '_boost', null_value: 1},
|
175
|
+
properties: {
|
176
|
+
name: {type: 'string', boost: 10, analyzer: 'my_analyzer'},
|
177
|
+
tags: {type: 'string', analyzer: 'my_analyzer'}
|
178
|
+
}
|
179
|
+
}
|
180
|
+
}
|
181
|
+
},
|
182
|
+
wrapper: :load
|
183
|
+
})
|
184
|
+
|
185
|
+
|
186
|
+
[Mapping definition docs](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-core-types.html)
|
187
|
+
|
188
|
+
### Pagination
|
189
|
+
|
190
|
+
```= paginate @posts``` should work as normal with Kaminari after you do:
|
191
|
+
|
192
|
+
@posts = Post.es.search(params[:search], page: params[:page])
|
193
|
+
# or
|
194
|
+
@posts = Post.es.search({
|
195
|
+
body: {
|
196
|
+
query: {
|
197
|
+
query_string: {
|
198
|
+
query: params[:search]
|
199
|
+
}
|
200
|
+
},
|
201
|
+
filter: {
|
202
|
+
term: {community_id: @community.id.to_s}
|
203
|
+
}
|
204
|
+
}},
|
205
|
+
page: params[:page], wrapper: :load
|
206
|
+
)
|
207
|
+
|
208
|
+
### Reindexing
|
209
|
+
|
210
|
+
#### All models
|
211
|
+
|
212
|
+
```rake es:reindex``` will reindex all indices managed by Mongoid::Elasticsearch
|
213
|
+
|
214
|
+
#### One model - Simple bulk
|
215
|
+
|
216
|
+
This is the preferred (fastest) method to reindex everything
|
217
|
+
|
218
|
+
Music::Video.es.index_all
|
219
|
+
|
220
|
+
#### One model - Simple
|
221
|
+
|
222
|
+
Communities::Thread.es.index.reset
|
223
|
+
Communities::Thread.enabled.each do |ingr|
|
224
|
+
ingr.es_update
|
225
|
+
end
|
226
|
+
|
227
|
+
### Possible wrappers for results:
|
228
|
+
|
229
|
+
- :hash - raw hash from ES
|
230
|
+
- :mash - [Hashie::Mash](https://github.com/intridea/hashie#mash) (gem '[hashie](https://github.com/intridea/hashie)' must be added to gemfile)
|
231
|
+
- :load - load each found model by ID from database
|
232
|
+
- :model - create a model instance from data stored in elasticsearch
|
233
|
+
|
234
|
+
See more examples in specs.
|
235
|
+
|
236
|
+
### Index creation
|
237
|
+
|
238
|
+
This gem by default automatically creates indexes for all configured models on application startup.
|
239
|
+
|
240
|
+
Set ```Mongoid::Elasticsearch.autocreate_indexes = false``` in an initalizer to prevent automatic creation for all indexes.
|
241
|
+
|
242
|
+
You can always use ```rake es:create``` to create all indexes or call ```Mongoid::Elasticsearch.create_all_indexes!```.
|
243
|
+
|
244
|
+
Indexes defined with option ```skip_create: true``` are not created with all other indexes and must be created manually with ```Model.es.index.create```
|
245
|
+
|
246
|
+
|
247
|
+
#### Util
|
248
|
+
|
249
|
+
# Escape string so it can be safely passed to ES (removes all special characters)
|
250
|
+
Mongoid::Elasticsearch::Utils.clean(s)
|
251
|
+
|
252
|
+
## Contributing
|
253
|
+
|
254
|
+
1. Fork it
|
255
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
256
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
257
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
258
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Elasticsearch
|
3
|
+
module Callbacks
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
after_save :update_es_index
|
8
|
+
after_destroy :update_es_index
|
9
|
+
|
10
|
+
## THIS FUNCTION HAS BEEN UPDATED TO DO THE UPDATE ONLY IF THE OP_SUCCESS IS TRUE OR NIL, IN CASE THE RECORD RESPONDS TO OP_SUCCESS.
|
11
|
+
def update_es_index
|
12
|
+
if self.respond_to? :op_success
|
13
|
+
if self.op_success.nil?
|
14
|
+
es_update
|
15
|
+
else
|
16
|
+
es_update if self.op_success == true
|
17
|
+
end
|
18
|
+
else
|
19
|
+
es_update
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
def without_es_update!( &block )
|
26
|
+
skip_callback( :save, :after, :update_es_index )
|
27
|
+
skip_callback( :destroy, :after, :update_es_index )
|
28
|
+
|
29
|
+
result = yield
|
30
|
+
|
31
|
+
set_callback( :save, :after, :update_es_index )
|
32
|
+
set_callback( :destroy, :after, :update_es_index )
|
33
|
+
|
34
|
+
result
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Elasticsearch
|
3
|
+
class Es
|
4
|
+
INDEX_STEP = 100
|
5
|
+
attr_reader :klass, :version
|
6
|
+
|
7
|
+
def initialize(klass)
|
8
|
+
@klass = klass
|
9
|
+
@version = Gem::Version.new(client.info['version']['number'])
|
10
|
+
end
|
11
|
+
|
12
|
+
def client
|
13
|
+
# dup is needed because Elasticsearch::Client.new changes options hash inplace
|
14
|
+
@client ||= ::Elasticsearch::Client.new klass.es_client_options.dup
|
15
|
+
end
|
16
|
+
|
17
|
+
def index
|
18
|
+
@index ||= Index.new(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def index_all(step_size = INDEX_STEP)
|
22
|
+
index.reset
|
23
|
+
q = klass.asc(:id)
|
24
|
+
steps = (q.count / step_size) + 1
|
25
|
+
last_id = nil
|
26
|
+
steps.times do |step|
|
27
|
+
if last_id
|
28
|
+
docs = q.gt(id: last_id).limit(step_size).to_a
|
29
|
+
else
|
30
|
+
docs = q.limit(step_size).to_a
|
31
|
+
end
|
32
|
+
last_id = docs.last.try(:id)
|
33
|
+
docs = docs.map do |obj|
|
34
|
+
if obj.es_index?
|
35
|
+
{ index: {data: obj.as_indexed_json}.merge(_id: obj.id.to_s) }
|
36
|
+
else
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end.reject { |obj| obj.nil? }
|
40
|
+
next if docs.empty?
|
41
|
+
client.bulk({body: docs}.merge(type_options))
|
42
|
+
if block_given?
|
43
|
+
yield steps, step
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def search(query, options = {})
|
49
|
+
if query.is_a?(String)
|
50
|
+
query = {q: Utils.clean(query)}
|
51
|
+
end
|
52
|
+
|
53
|
+
page = options[:page]
|
54
|
+
per_page = options[:per_page].nil? ? options[:per] : options[:per_page]
|
55
|
+
|
56
|
+
query[:size] = ( per_page.to_i ) if per_page
|
57
|
+
query[:from] = ( page.to_i <= 1 ? 0 : (per_page.to_i * (page.to_i-1)) ) if page && per_page
|
58
|
+
|
59
|
+
options[:wrapper] ||= klass.es_wrapper
|
60
|
+
|
61
|
+
Response.new(client, query.merge(custom_type_options(options)), false, klass, options)
|
62
|
+
end
|
63
|
+
|
64
|
+
def all(options = {})
|
65
|
+
search({body: {query: {match_all: {}}}}, options)
|
66
|
+
end
|
67
|
+
|
68
|
+
def options_for(obj)
|
69
|
+
{id: obj.id.to_s}.merge type_options
|
70
|
+
end
|
71
|
+
|
72
|
+
def custom_type_options(options)
|
73
|
+
if !options[:include_type].nil? && options[:include_type] == false
|
74
|
+
{index: index.name}
|
75
|
+
else
|
76
|
+
type_options
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def type_options
|
81
|
+
{index: index.name, type: index.type}
|
82
|
+
end
|
83
|
+
|
84
|
+
def index_item(obj)
|
85
|
+
client.index({body: obj.as_indexed_json}.merge(options_for(obj)))
|
86
|
+
end
|
87
|
+
|
88
|
+
def remove_item(obj)
|
89
|
+
client.delete(options_for(obj).merge(ignore: 404))
|
90
|
+
end
|
91
|
+
|
92
|
+
def completion_supported?
|
93
|
+
@version > Gem::Version.new('0.90.2')
|
94
|
+
end
|
95
|
+
|
96
|
+
def completion(text, field = "suggest")
|
97
|
+
raise "Completion not supported in ES #{@version}" unless completion_supported?
|
98
|
+
body = {
|
99
|
+
q: {
|
100
|
+
text: Utils.clean(text),
|
101
|
+
completion: {
|
102
|
+
field: field
|
103
|
+
}
|
104
|
+
}
|
105
|
+
}
|
106
|
+
results = client.suggest(index: index.name, body: body)
|
107
|
+
results['q'][0]['options']
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|