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
@@ -0,0 +1,62 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Elasticsearch
|
3
|
+
class Index
|
4
|
+
def initialize(es)
|
5
|
+
@es = es
|
6
|
+
end
|
7
|
+
|
8
|
+
def klass
|
9
|
+
@es.klass
|
10
|
+
end
|
11
|
+
|
12
|
+
def name
|
13
|
+
klass.es_index_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def type
|
17
|
+
klass.model_name.collection.singularize
|
18
|
+
end
|
19
|
+
|
20
|
+
def options
|
21
|
+
klass.es_index_options
|
22
|
+
end
|
23
|
+
|
24
|
+
def indices
|
25
|
+
@es.client.indices
|
26
|
+
end
|
27
|
+
|
28
|
+
def exists?
|
29
|
+
indices.exists index: name
|
30
|
+
end
|
31
|
+
|
32
|
+
def create
|
33
|
+
unless options == {} || exists?
|
34
|
+
force_create
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def force_create
|
39
|
+
indices.create index: name, body: options
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete
|
43
|
+
if exists?
|
44
|
+
force_delete
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def force_delete
|
49
|
+
indices.delete index: name
|
50
|
+
end
|
51
|
+
|
52
|
+
def refresh
|
53
|
+
indices.refresh index: name
|
54
|
+
end
|
55
|
+
|
56
|
+
def reset
|
57
|
+
delete
|
58
|
+
create
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Elasticsearch
|
3
|
+
module Indexing
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
included do
|
6
|
+
def as_indexed_json
|
7
|
+
serializable_hash.reject { |k, v| %w(_id c_at u_at created_at updated_at).include?(k) }
|
8
|
+
end
|
9
|
+
|
10
|
+
def es_index?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def es_update
|
15
|
+
if destroyed? || !es_index?
|
16
|
+
self.class.es.remove_item(self)
|
17
|
+
else
|
18
|
+
self.class.es.index_item(self)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Quick fix for https://github.com/elasticsearch/elasticsearch-ruby/issues/43
|
2
|
+
|
3
|
+
require 'elasticsearch/api/actions/search'
|
4
|
+
module Elasticsearch
|
5
|
+
module API
|
6
|
+
module Actions
|
7
|
+
def search(arguments={})
|
8
|
+
arguments[:index] = '_all' if ! arguments[:index] && arguments[:type]
|
9
|
+
|
10
|
+
valid_params = [
|
11
|
+
:analyzer,
|
12
|
+
:analyze_wildcard,
|
13
|
+
:default_operator,
|
14
|
+
:df,
|
15
|
+
:explain,
|
16
|
+
:fields,
|
17
|
+
:from,
|
18
|
+
:ignore_indices,
|
19
|
+
:ignore_unavailable,
|
20
|
+
:allow_no_indices,
|
21
|
+
:expand_wildcards,
|
22
|
+
:indices_boost,
|
23
|
+
:lenient,
|
24
|
+
:lowercase_expanded_terms,
|
25
|
+
:preference,
|
26
|
+
:q,
|
27
|
+
:routing,
|
28
|
+
:scroll,
|
29
|
+
:search_type,
|
30
|
+
:size,
|
31
|
+
:sort,
|
32
|
+
:source,
|
33
|
+
:_source,
|
34
|
+
:_source_include,
|
35
|
+
:_source_exclude,
|
36
|
+
:stats,
|
37
|
+
:suggest_field,
|
38
|
+
:suggest_mode,
|
39
|
+
:suggest_size,
|
40
|
+
:suggest_text,
|
41
|
+
:timeout,
|
42
|
+
:version ]
|
43
|
+
|
44
|
+
method = 'GET'
|
45
|
+
path = Utils.__pathify( Utils.__listify(arguments[:index]), Utils.__listify(arguments[:type]), '_search' )
|
46
|
+
|
47
|
+
params = Utils.__validate_and_extract_params arguments, valid_params
|
48
|
+
body = arguments[:body]
|
49
|
+
|
50
|
+
params[:fields] = Utils.__listify(params[:fields]) if params[:fields]
|
51
|
+
|
52
|
+
perform_request(method, path, params, body).body
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# credits: https://github.com/karmi/retire/blob/master/lib/tire/results/pagination.rb
|
2
|
+
|
3
|
+
|
4
|
+
module Mongoid
|
5
|
+
module Elasticsearch
|
6
|
+
# Adds support for WillPaginate and Kaminari
|
7
|
+
module Pagination
|
8
|
+
def total_entries
|
9
|
+
total
|
10
|
+
end
|
11
|
+
|
12
|
+
def per_page
|
13
|
+
(@options[:per_page] || @options[:per] || @options[:size] || 10 ).to_i
|
14
|
+
end
|
15
|
+
|
16
|
+
def total_pages
|
17
|
+
( total.to_f / per_page ).ceil
|
18
|
+
end
|
19
|
+
|
20
|
+
def current_page
|
21
|
+
if @options[:page]
|
22
|
+
@options[:page].to_i
|
23
|
+
else
|
24
|
+
(per_page + @options[:from].to_i) / per_page
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def previous_page
|
29
|
+
current_page > 1 ? (current_page - 1) : nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def next_page
|
33
|
+
current_page < total_pages ? (current_page + 1) : nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def offset
|
37
|
+
per_page * (current_page - 1)
|
38
|
+
end
|
39
|
+
|
40
|
+
def out_of_bounds?
|
41
|
+
current_page > total_pages
|
42
|
+
end
|
43
|
+
|
44
|
+
# Kaminari support
|
45
|
+
#
|
46
|
+
alias :limit_value :per_page
|
47
|
+
alias :total_count :total_entries
|
48
|
+
alias :num_pages :total_pages
|
49
|
+
alias :offset_value :offset
|
50
|
+
alias :out_of_range? :out_of_bounds?
|
51
|
+
|
52
|
+
def first_page?
|
53
|
+
current_page == 1
|
54
|
+
end
|
55
|
+
|
56
|
+
def last_page?
|
57
|
+
total_pages == 0 || current_page == total_pages
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Mongoid::Elasticsearch
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
rake_tasks do
|
4
|
+
require File.expand_path('../tasks', __FILE__)
|
5
|
+
end
|
6
|
+
|
7
|
+
config.after_initialize do
|
8
|
+
Mongoid::Elasticsearch.create_all_indexes! if Mongoid::Elasticsearch.autocreate_indexes
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
# partially based on https://github.com/karmi/retire/blob/master/lib/tire/results/collection.rb
|
2
|
+
|
3
|
+
require 'mongoid/elasticsearch/pagination'
|
4
|
+
|
5
|
+
module Mongoid
|
6
|
+
module Elasticsearch
|
7
|
+
class Response
|
8
|
+
include Enumerable
|
9
|
+
include Pagination
|
10
|
+
|
11
|
+
attr_reader :time, :total, :options, :facets, :max
|
12
|
+
attr_reader :response
|
13
|
+
|
14
|
+
def initialize(client, query, multi, model, options)
|
15
|
+
@client = client
|
16
|
+
@query = query
|
17
|
+
@multi = multi
|
18
|
+
@model = model
|
19
|
+
@wrapper = options[:wrapper]
|
20
|
+
@options = options
|
21
|
+
end
|
22
|
+
|
23
|
+
def perform!
|
24
|
+
response = @client.search(@query)
|
25
|
+
@options = options
|
26
|
+
@time = response['took'].to_i
|
27
|
+
@total = response['hits']['total'].to_i rescue nil
|
28
|
+
@facets = response['facets']
|
29
|
+
@max_score = response['hits']['max_score'].to_f rescue nil
|
30
|
+
response
|
31
|
+
end
|
32
|
+
|
33
|
+
def total
|
34
|
+
if @total.nil?
|
35
|
+
perform!
|
36
|
+
@total
|
37
|
+
else
|
38
|
+
@total
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def raw_response
|
43
|
+
@raw_response ||= perform!
|
44
|
+
end
|
45
|
+
|
46
|
+
def hits
|
47
|
+
@hits ||= raw_response['hits']['hits']
|
48
|
+
end
|
49
|
+
|
50
|
+
def results
|
51
|
+
return [] if failure?
|
52
|
+
@results ||= begin
|
53
|
+
case @wrapper
|
54
|
+
when :load
|
55
|
+
if @multi
|
56
|
+
multi_with_load
|
57
|
+
else
|
58
|
+
records = @model.find(hits.map { |h| h['_id'] })
|
59
|
+
hits.map do |item|
|
60
|
+
records.detect do |record|
|
61
|
+
record.id.to_s == item['_id'].to_s
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
when :mash
|
66
|
+
hits.map do |h|
|
67
|
+
s = h.delete('_source')
|
68
|
+
m = Hashie::Mash.new(h.merge(s))
|
69
|
+
if defined?(Moped::BSON)
|
70
|
+
m.id = Moped::BSON::ObjectId.from_string(h['_id'])
|
71
|
+
else
|
72
|
+
m.id = BSON::ObjectId.from_string(h['_id'])
|
73
|
+
end
|
74
|
+
m._id = m.id
|
75
|
+
m
|
76
|
+
end
|
77
|
+
when :model
|
78
|
+
multi_without_load
|
79
|
+
else
|
80
|
+
hits
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def error
|
87
|
+
raw_response['error']
|
88
|
+
end
|
89
|
+
|
90
|
+
def success?
|
91
|
+
error.to_s.empty?
|
92
|
+
end
|
93
|
+
|
94
|
+
def failure?
|
95
|
+
!success?
|
96
|
+
end
|
97
|
+
|
98
|
+
def each(&block)
|
99
|
+
results.each(&block)
|
100
|
+
end
|
101
|
+
|
102
|
+
def to_ary
|
103
|
+
results
|
104
|
+
end
|
105
|
+
|
106
|
+
def inspect
|
107
|
+
"#<Mongoid::Elasticsearch::Response @size:#{@results.nil? ? 'not run yet' : size} @results:#{@results.inspect} @raw_response=#{@raw_response}>"
|
108
|
+
end
|
109
|
+
|
110
|
+
def count
|
111
|
+
# returns approximate counts, for now just using search_type: 'count',
|
112
|
+
# which is exact
|
113
|
+
# @total ||= @client.count(@query)['count']
|
114
|
+
|
115
|
+
@total ||= @client.search(@query.merge(search_type: 'count'))['hits']['total']
|
116
|
+
end
|
117
|
+
|
118
|
+
def size
|
119
|
+
results.size
|
120
|
+
end
|
121
|
+
alias_method :length, :size
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def find_klass(type)
|
126
|
+
raise NoMethodError, "You have tried to eager load the model instances, " +
|
127
|
+
"but Mongoid::Elasticsearch cannot find the model class because " +
|
128
|
+
"document has no _type property." unless type
|
129
|
+
|
130
|
+
begin
|
131
|
+
klass = type.camelize.singularize.constantize
|
132
|
+
rescue NameError => e
|
133
|
+
raise NameError, "You have tried to eager load the model instances, but " +
|
134
|
+
"Mongoid::Elasticsearch cannot find the model class '#{type.camelize}' " +
|
135
|
+
"based on _type '#{type}'.", e.backtrace
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def multi_with_load
|
140
|
+
return [] if hits.empty?
|
141
|
+
|
142
|
+
records = {}
|
143
|
+
hits.group_by { |item| item['_type'] }.each do |type, items|
|
144
|
+
klass = find_klass(type)
|
145
|
+
records[type] = klass.find(items.map { |h| h['_id'] })
|
146
|
+
end
|
147
|
+
|
148
|
+
# Reorder records to preserve the order from search results
|
149
|
+
hits.map do |item|
|
150
|
+
records[item['_type']].detect do |record|
|
151
|
+
record.id.to_s == item['_id'].to_s
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def multi_without_load
|
157
|
+
hits.map do |h|
|
158
|
+
klass = find_klass(h['_type'])
|
159
|
+
h[:_highlight] = h.delete('highlight') if h.key?('highlight')
|
160
|
+
source = h.delete('_source')
|
161
|
+
if defined?(Moped::BSON)
|
162
|
+
source.each do |k,v|
|
163
|
+
if v.is_a?(Hash) && v.has_key?("$oid")
|
164
|
+
source[k] = Moped::BSON::ObjectId.from_string(v["$oid"])
|
165
|
+
end
|
166
|
+
end
|
167
|
+
else
|
168
|
+
source.each do |k,v|
|
169
|
+
if v.is_a?(Hash) && v.has_key?("$oid")
|
170
|
+
source[k] = BSON::ObjectId.from_string(v["$oid"])
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
begin
|
175
|
+
m = klass.new(h.merge(source))
|
176
|
+
if defined?(Moped::BSON)
|
177
|
+
m.id = Moped::BSON::ObjectId.from_string(h['_id'])
|
178
|
+
else
|
179
|
+
m.id = BSON::ObjectId.from_string(h['_id'])
|
180
|
+
end
|
181
|
+
rescue Mongoid::Errors::UnknownAttribute
|
182
|
+
klass.class_eval <<-RUBY, __FILE__, __LINE__+1
|
183
|
+
attr_accessor :_type, :_score, :_source, :_highlight
|
184
|
+
RUBY
|
185
|
+
m = klass.new(h.merge(source))
|
186
|
+
end
|
187
|
+
m.new_record = false
|
188
|
+
m
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# require this file to load the tasks
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
# Require sitemap_generator at runtime. If we don't do this the ActionView helpers are included
|
5
|
+
# before the Rails environment can be loaded by other Rake tasks, which causes problems
|
6
|
+
# for those tasks when rendering using ActionView.
|
7
|
+
namespace :es do
|
8
|
+
# Require sitemap_generator only. When installed as a plugin the require will fail, so in
|
9
|
+
# that case, load the environment first.
|
10
|
+
task :require do
|
11
|
+
Rake::Task['environment'].invoke
|
12
|
+
require 'ruby-progressbar'
|
13
|
+
end
|
14
|
+
desc "create all indexes"
|
15
|
+
task :create => ['es:require'] do
|
16
|
+
Mongoid::Elasticsearch.create_all_indexes!
|
17
|
+
end
|
18
|
+
desc "reindex all ES models"
|
19
|
+
task :reindex => ['es:require'] do
|
20
|
+
Mongoid::Elasticsearch.registered_models.each do |model_name|
|
21
|
+
pb = nil
|
22
|
+
model_name.constantize.es.index_all do |steps, step|
|
23
|
+
pb = ProgressBar.create(title: model_name, total: steps, format: '%t: %p%% %a |%b>%i| %E') if pb.nil?
|
24
|
+
pb.increment
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# source: https://github.com/karmi/retire/blob/master/lib/tire/utils.rb
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module Mongoid
|
6
|
+
module Elasticsearch
|
7
|
+
module Utils
|
8
|
+
def clean(s)
|
9
|
+
s.to_s.gsub(/\P{Word}+/, ' ').gsub(/ +/, ' ').strip
|
10
|
+
end
|
11
|
+
|
12
|
+
extend self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'elasticsearch'
|
2
|
+
require 'mongoid/elasticsearch/version'
|
3
|
+
|
4
|
+
require 'active_support/concern'
|
5
|
+
|
6
|
+
require 'mongoid/elasticsearch/utils'
|
7
|
+
require 'mongoid/elasticsearch/es'
|
8
|
+
require 'mongoid/elasticsearch/callbacks'
|
9
|
+
require 'mongoid/elasticsearch/index'
|
10
|
+
require 'mongoid/elasticsearch/indexing'
|
11
|
+
require 'mongoid/elasticsearch/response'
|
12
|
+
|
13
|
+
require 'mongoid/elasticsearch/monkeypatches'
|
14
|
+
|
15
|
+
module Mongoid
|
16
|
+
module Elasticsearch
|
17
|
+
mattr_accessor :autocreate_indexes
|
18
|
+
self.autocreate_indexes = true
|
19
|
+
|
20
|
+
mattr_accessor :prefix
|
21
|
+
self.prefix = ''
|
22
|
+
|
23
|
+
mattr_accessor :client_options
|
24
|
+
self.client_options = {}
|
25
|
+
|
26
|
+
mattr_accessor :registered_indexes
|
27
|
+
self.registered_indexes = []
|
28
|
+
|
29
|
+
mattr_accessor :registered_models
|
30
|
+
self.registered_models = []
|
31
|
+
|
32
|
+
extend ActiveSupport::Concern
|
33
|
+
included do
|
34
|
+
def self.es
|
35
|
+
@__es__ ||= Mongoid::Elasticsearch::Es.new(self)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Add elasticsearch to the model
|
39
|
+
# @option index_name [String] name of the index for this model
|
40
|
+
# @option index_options [Hash] Index options to be passed to Elasticsearch
|
41
|
+
# when creating an index
|
42
|
+
# @option client_options [Hash] Options for Elasticsearch::Client.new
|
43
|
+
# @option wrapper [Symbol] Select what wrapper to use for results
|
44
|
+
# possible options:
|
45
|
+
# :model - creates a new model instance, set its attributes, and marks it as persisted
|
46
|
+
# :mash - Hashie::Mash for object-like access (perfect for simple models, needs gem 'hashie')
|
47
|
+
# :none - raw hash
|
48
|
+
# :load - load models from Mongo by IDs
|
49
|
+
def self.elasticsearch!(options = {})
|
50
|
+
options = {
|
51
|
+
prefix_name: true,
|
52
|
+
index_name: nil,
|
53
|
+
client_options: {},
|
54
|
+
index_options: {},
|
55
|
+
index_mappings: nil,
|
56
|
+
wrapper: :model,
|
57
|
+
callbacks: true,
|
58
|
+
skip_create: false
|
59
|
+
}.merge(options)
|
60
|
+
|
61
|
+
if options[:wrapper] == :model
|
62
|
+
attr_accessor :_type, :_score, :_source
|
63
|
+
end
|
64
|
+
|
65
|
+
cattr_accessor :es_client_options, :es_index_name, :es_index_options, :es_wrapper, :es_skip_create
|
66
|
+
|
67
|
+
self.es_client_options = Mongoid::Elasticsearch.client_options.dup.merge(options[:client_options])
|
68
|
+
self.es_index_name = (options[:prefix_name] ? Mongoid::Elasticsearch.prefix : '') + (options[:index_name] || model_name.plural)
|
69
|
+
self.es_index_options = options[:index_options]
|
70
|
+
self.es_wrapper = options[:wrapper]
|
71
|
+
self.es_skip_create = options[:skip_create]
|
72
|
+
|
73
|
+
Mongoid::Elasticsearch.registered_indexes.push self.es_index_name
|
74
|
+
Mongoid::Elasticsearch.registered_indexes.uniq!
|
75
|
+
|
76
|
+
Mongoid::Elasticsearch.registered_models.push self.name
|
77
|
+
Mongoid::Elasticsearch.registered_models.uniq!
|
78
|
+
|
79
|
+
unless options[:index_mappings].nil?
|
80
|
+
self.es_index_options = self.es_index_options.deep_merge({
|
81
|
+
:mappings => {
|
82
|
+
es.index.type.to_sym => {
|
83
|
+
:properties => options[:index_mappings]
|
84
|
+
}
|
85
|
+
}
|
86
|
+
})
|
87
|
+
end
|
88
|
+
|
89
|
+
include Indexing
|
90
|
+
include Callbacks if options[:callbacks]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.create_all_indexes!
|
95
|
+
# puts "creating ES indexes"
|
96
|
+
Mongoid::Elasticsearch.registered_models.each do |model_name|
|
97
|
+
model = model_name.constantize
|
98
|
+
model.es.index.create unless model.es_skip_create
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# search multiple models
|
103
|
+
def self.search(query, options = {})
|
104
|
+
if query.is_a?(String)
|
105
|
+
query = {q: Utils.clean(query)}
|
106
|
+
end
|
107
|
+
# use `_all` or empty string to perform the operation on all indices
|
108
|
+
# regardless whether they are managed by Mongoid::Elasticsearch or not
|
109
|
+
unless query.key?(:index)
|
110
|
+
query.merge!(index: Mongoid::Elasticsearch.registered_indexes.join(','), ignore_indices: 'missing', ignore_unavailable: true)
|
111
|
+
end
|
112
|
+
|
113
|
+
page = options[:page]
|
114
|
+
per_page = options[:per_page]
|
115
|
+
|
116
|
+
query[:size] = ( per_page.to_i ) if per_page
|
117
|
+
query[:from] = ( page.to_i <= 1 ? 0 : (per_page.to_i * (page.to_i-1)) ) if page && per_page
|
118
|
+
|
119
|
+
options[:wrapper] ||= :model
|
120
|
+
|
121
|
+
client = ::Elasticsearch::Client.new Mongoid::Elasticsearch.client_options.dup
|
122
|
+
Response.new(client, query, true, nil, options)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
if defined? Rails
|
128
|
+
require 'mongoid/elasticsearch/railtie'
|
129
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'mongoid/elasticsearch'
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mongoid/elasticsearch/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "wj-mongoid-elasticsearch"
|
8
|
+
spec.version = Mongoid::Elasticsearch::VERSION
|
9
|
+
spec.authors = ["glebtv"]
|
10
|
+
spec.email = ["glebtv@gmail.com"]
|
11
|
+
spec.description = %q{Simple and easy integration of mongoid with the new elasticsearch gem}
|
12
|
+
spec.summary = %q{Simple and easy integration of mongoid with the new elasticsearch gem}
|
13
|
+
spec.homepage = "https://github.com/rs-pro/mongoid-elasticsearch"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "mongoid", [">= 3.0", "< 6.0"]
|
22
|
+
spec.add_dependency "elasticsearch", "~> 1.0.13"
|
23
|
+
spec.add_dependency "ruby-progressbar"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
spec.add_development_dependency "rspec"
|
28
|
+
spec.add_development_dependency "kaminari"
|
29
|
+
spec.add_development_dependency "database_cleaner"
|
30
|
+
spec.add_development_dependency "coveralls"
|
31
|
+
spec.add_development_dependency "hashie"
|
32
|
+
spec.add_development_dependency "mongoid-slug", '~> 5.0.0'
|
33
|
+
spec.add_development_dependency "glebtv-httpclient"
|
34
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Article
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Timestamps::Short
|
4
|
+
#include ActiveModel::ForbiddenAttributesProtection
|
5
|
+
|
6
|
+
field :name
|
7
|
+
|
8
|
+
include Mongoid::Slug
|
9
|
+
slug :name
|
10
|
+
|
11
|
+
field :tags
|
12
|
+
|
13
|
+
include Mongoid::Elasticsearch
|
14
|
+
i_fields = {
|
15
|
+
name: {type: 'string', analyzer: 'snowball'},
|
16
|
+
raw: {type: 'string', index: :not_analyzed}
|
17
|
+
}
|
18
|
+
|
19
|
+
if Gem::Version.new(::Elasticsearch::Client.new.info['version']['number']) > Gem::Version.new('0.90.2')
|
20
|
+
i_fields[:suggest] = {type: 'completion'}
|
21
|
+
end
|
22
|
+
|
23
|
+
elasticsearch! index_name: 'mongoid_es_news', prefix_name: false, index_mappings: {
|
24
|
+
name: {
|
25
|
+
type: 'multi_field',
|
26
|
+
fields: i_fields
|
27
|
+
},
|
28
|
+
_slugs: {type: 'string', index: :not_analyzed},
|
29
|
+
tags: {type: 'string', include_in_all: false}
|
30
|
+
}, wrapper: :load
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Namespaced
|
2
|
+
class Model
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Timestamps::Short
|
5
|
+
#include ActiveModel::ForbiddenAttributesProtection
|
6
|
+
|
7
|
+
field :name
|
8
|
+
|
9
|
+
include Mongoid::Elasticsearch
|
10
|
+
elasticsearch! index_options: {
|
11
|
+
'namespaced/model' => {
|
12
|
+
mappings: {
|
13
|
+
properties: {
|
14
|
+
name: {
|
15
|
+
type: 'string'
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|