wj-mongoid-elasticsearch 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/rs-pro/mongoid-elasticsearch.png?branch=master)](https://travis-ci.org/rs-pro/mongoid-elasticsearch)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/rs-pro/mongoid-elasticsearch/badge.png?branch=master)](https://coveralls.io/r/rs-pro/mongoid-elasticsearch?branch=master)
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/mongoid-elasticsearch.png)](http://badge.fury.io/rb/mongoid-elasticsearch)
|
6
|
+
[![Dependency Status](https://www.versioneye.com/user/projects/53e73fe735080d1e4d00009c/badge.svg)](https://www.versioneye.com/user/projects/53e73fe735080d1e4d00009c)
|
7
|
+
[![Issues](http://img.shields.io/github/issues/rs-pro/mongoid-elasticsearch.svg)](https://github.com/rs-pro/mongoid-elasticsearch/issues)
|
8
|
+
[![License](http://img.shields.io/:license-mit-blue.svg)](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
|