mongoid_search 0.3.5 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +26 -1
- data/VERSION +1 -1
- data/lib/mongoid_search.rb +1 -1
- data/lib/mongoid_search/mongoid_search.rb +28 -11
- data/spec/models/product.rb +3 -0
- data/spec/models/variant.rb +2 -0
- data/spec/mongoid_search_spec.rb +21 -5
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65d13fcd90c890df7b15f2175b701e951259f8de
|
4
|
+
data.tar.gz: '097843e60c25fc38ddb96789093dc798a08c5739'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a13b1d7f1bce08ffed931346ec1b1b6750ad984aeb263d93fc1c1db3dd8d03761a763958fb8d000ec19b0ea98b791e3d15020cd152375dbc5d5e19338cc5944f
|
7
|
+
data.tar.gz: 71008ecd40e79df705f769d03e0b03953a3278b3cb46ceb325b212e48b8c1321c58aa540750b094d8a94cc9082cbd66e13bba145ebfc7c0af6f78ce7a72fa796
|
data/README.md
CHANGED
@@ -26,12 +26,14 @@ class Product
|
|
26
26
|
include Mongoid::Search
|
27
27
|
field :brand
|
28
28
|
field :name
|
29
|
+
field :unit
|
29
30
|
field :info, type: Hash
|
30
31
|
|
31
32
|
has_many :tags
|
32
33
|
belongs_to :category
|
33
34
|
|
34
35
|
search_in :brand, :name, tags: :name, category: :name, info: %i[summary description]
|
36
|
+
search_in :unit, index: :_unit_keywords
|
35
37
|
end
|
36
38
|
|
37
39
|
class Tag
|
@@ -52,7 +54,7 @@ end
|
|
52
54
|
Now when you save a product, you get a `_keywords` field automatically:
|
53
55
|
|
54
56
|
```ruby
|
55
|
-
p = Product.new brand: 'Apple', name: 'iPhone', info: { summary: 'Info-summary', description: 'Info-description' }
|
57
|
+
p = Product.new brand: 'Apple', name: 'iPhone', unit: 'kilogram', info: { summary: 'Info-summary', description: 'Info-description' }
|
56
58
|
p.tags << Tag.new(name: 'Amazing')
|
57
59
|
p.tags << Tag.new(name: 'Awesome')
|
58
60
|
p.tags << Tag.new(name: 'Superb')
|
@@ -60,6 +62,8 @@ p.save
|
|
60
62
|
# => true
|
61
63
|
p._keywords
|
62
64
|
# => ["amazing", "apple", "awesome", "iphone", "superb", "Info-summary", "Info-description"]
|
65
|
+
p._unit_keywords
|
66
|
+
# => ["kilogram"]
|
63
67
|
```
|
64
68
|
|
65
69
|
Now you can run search, which will look in the `_keywords` field and return all matching results:
|
@@ -69,6 +73,13 @@ Product.full_text_search("apple iphone").size
|
|
69
73
|
# => 1
|
70
74
|
```
|
71
75
|
|
76
|
+
Of course, some models could have more than one index. For instance, two different searches with different fields, so you could even specify from which index should be searched:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
Product.full_text_search("kilogram", index: :_unit_keywords).size
|
80
|
+
# => 1
|
81
|
+
```
|
82
|
+
|
72
83
|
Note that the search is case insensitive, and accept partial searching too:
|
73
84
|
|
74
85
|
```ruby
|
@@ -131,6 +142,20 @@ Product.full_text_search('amazing apple', relevant_search: true)
|
|
131
142
|
|
132
143
|
Please note that relevant_search will return an Array and not a Criteria object. The search method should always be called in the end of the method chain.
|
133
144
|
|
145
|
+
### index
|
146
|
+
|
147
|
+
Default is `_keywords`.
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
Product.full_text_search('amazing apple', index: :_keywords)
|
151
|
+
# => [#<Product _id: 5016e7d16af54efe1c000001, _type: nil, brand: "Apple", name: "iPhone", unit: "l", attrs: nil, info: nil, category_id: nil, _keywords: ["amazing", "apple", "awesome", "iphone", "superb"], _unit_keywords: ["l"], relevance: 2.0>]
|
152
|
+
|
153
|
+
Product.full_text_search('kg', index: :_unit_keywords)
|
154
|
+
# => [#<Product _id: 5016e7d16af54efe1c000001, _type: nil, brand: "Apple", name: "iPhone", unit: "kg", attrs: nil, info: nil, category_id: nil, _keywords: ["amazing", "apple", "awesome", "iphone", "superb"], _unit_keywords: ["kg"], relevance: 2.0>]
|
155
|
+
```
|
156
|
+
|
157
|
+
index enables to have two or more different searches, with different or same fields. It should be noted that indexes are exclusive per each one.
|
158
|
+
|
134
159
|
## Initializer
|
135
160
|
|
136
161
|
Alternatively, you can create an initializer to setup those options:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.6
|
data/lib/mongoid_search.rb
CHANGED
@@ -50,7 +50,7 @@ module Mongoid::Search
|
|
50
50
|
# Ligatures to be replaced
|
51
51
|
# http://en.wikipedia.org/wiki/Typographic_ligature
|
52
52
|
mattr_accessor :ligatures
|
53
|
-
@@ligatures = { 'œ' => 'oe', 'æ' => 'ae' }
|
53
|
+
@@ligatures = { 'œ' => 'oe', 'æ' => 'ae', 'ꜵ' => 'ao' }
|
54
54
|
|
55
55
|
# Minimum word size. Words smaller than it won't be indexed
|
56
56
|
mattr_accessor :minimum_word_size
|
@@ -14,12 +14,12 @@ module Mongoid::Search
|
|
14
14
|
module ClassMethods #:nodoc:
|
15
15
|
# Set a field or a number of fields as sources for search
|
16
16
|
def search_in(*args)
|
17
|
-
args,
|
18
|
-
|
17
|
+
args, options = args_and_options(args)
|
18
|
+
set_search_fields(options[:index], args)
|
19
19
|
|
20
|
-
field :
|
20
|
+
field options[:index], type: Array
|
21
21
|
|
22
|
-
index({
|
22
|
+
index({ options[:index] => 1 }, background: true)
|
23
23
|
|
24
24
|
before_save :set_keywords
|
25
25
|
end
|
@@ -49,13 +49,20 @@ module Mongoid::Search
|
|
49
49
|
|
50
50
|
private
|
51
51
|
|
52
|
+
def set_search_fields(index, fields)
|
53
|
+
self.search_fields ||= {}
|
54
|
+
|
55
|
+
(self.search_fields[index] ||= []).concat fields
|
56
|
+
end
|
57
|
+
|
52
58
|
def query(keywords, options)
|
53
59
|
keywords_hash = keywords.map do |kw|
|
54
60
|
if Mongoid::Search.regex_search
|
55
61
|
escaped_kw = Regexp.escape(kw)
|
56
62
|
kw = Mongoid::Search.regex.call(escaped_kw)
|
57
63
|
end
|
58
|
-
|
64
|
+
|
65
|
+
{ options[:index] => kw }
|
59
66
|
end
|
60
67
|
|
61
68
|
criteria.send("#{(options[:match])}_of", *keywords_hash)
|
@@ -65,6 +72,7 @@ module Mongoid::Search
|
|
65
72
|
options = args.last.is_a?(Hash) &&
|
66
73
|
%i[match
|
67
74
|
allow_empty_search
|
75
|
+
index
|
68
76
|
relevant_search].include?(args.last.keys.first) ? args.pop : {}
|
69
77
|
|
70
78
|
[args, extract_options(options)]
|
@@ -74,7 +82,8 @@ module Mongoid::Search
|
|
74
82
|
{
|
75
83
|
match: options[:match] || Mongoid::Search.match,
|
76
84
|
allow_empty_search: options[:allow_empty_search] || Mongoid::Search.allow_empty_search,
|
77
|
-
relevant_search: options[:relevant_search] || Mongoid::Search.relevant_search
|
85
|
+
relevant_search: options[:relevant_search] || Mongoid::Search.relevant_search,
|
86
|
+
index: options[:index] || :_keywords
|
78
87
|
}
|
79
88
|
end
|
80
89
|
|
@@ -99,8 +108,8 @@ module Mongoid::Search
|
|
99
108
|
function() {
|
100
109
|
var entries = 0;
|
101
110
|
for(i in keywords) {
|
102
|
-
for(j in this
|
103
|
-
if(this
|
111
|
+
for(j in this.#{options[:index]}) {
|
112
|
+
if(this.#{options[:index]}[j] == keywords[i]) {
|
104
113
|
entries++;
|
105
114
|
}
|
106
115
|
}
|
@@ -122,11 +131,19 @@ module Mongoid::Search
|
|
122
131
|
end
|
123
132
|
|
124
133
|
def index_keywords!
|
125
|
-
|
134
|
+
search_fields.map do |index, fields|
|
135
|
+
update_attribute(index, get_keywords(fields))
|
136
|
+
end
|
126
137
|
end
|
127
138
|
|
128
139
|
def set_keywords
|
129
|
-
|
130
|
-
|
140
|
+
search_fields.each do |index, fields|
|
141
|
+
send("#{index}=", get_keywords(fields))
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def get_keywords(fields)
|
146
|
+
Mongoid::Search::Util.keywords(self, fields)
|
147
|
+
.flatten.reject { |k| k.nil? || k.empty? }.uniq.sort
|
131
148
|
end
|
132
149
|
end
|
data/spec/models/product.rb
CHANGED
@@ -5,6 +5,8 @@ class Product
|
|
5
5
|
|
6
6
|
field :brand
|
7
7
|
field :name
|
8
|
+
field :unit
|
9
|
+
field :measures, type: Array
|
8
10
|
field :attrs, type: Array
|
9
11
|
field :info, type: Hash
|
10
12
|
|
@@ -18,4 +20,5 @@ class Product
|
|
18
20
|
|
19
21
|
search_in :brand, :name, :outlet, :attrs, tags: :name, category: %i[name description],
|
20
22
|
subproducts: %i[brand name], info: %i[summary description]
|
23
|
+
search_in :unit, :measures, index: :_unit_keywords
|
21
24
|
end
|
data/spec/models/variant.rb
CHANGED
data/spec/mongoid_search_spec.rb
CHANGED
@@ -18,6 +18,7 @@ describe Mongoid::Search do
|
|
18
18
|
Mongoid::Search.stem_proc = @default_proc
|
19
19
|
@product = Product.create brand: 'Apple',
|
20
20
|
name: 'iPhone',
|
21
|
+
unit: 'mobile olé awesome',
|
21
22
|
tags: (@tags = %w[Amazing Awesome Olé].map { |tag| Tag.new(name: tag) }),
|
22
23
|
category: Category.new(name: 'Mobile', description: 'Reviews'),
|
23
24
|
subproducts: [Subproduct.new(brand: 'Apple', name: 'Craddle')],
|
@@ -52,6 +53,7 @@ describe Mongoid::Search do
|
|
52
53
|
Mongoid::Search.ignore_list = nil
|
53
54
|
@product = Product.create brand: 'Эльбрус',
|
54
55
|
name: 'Процессор',
|
56
|
+
unit: 'kílográm Olé',
|
55
57
|
tags: %w[Amazing Awesome Olé].map { |tag| Tag.new(name: tag) },
|
56
58
|
category: Category.new(name: 'процессоры'),
|
57
59
|
subproducts: []
|
@@ -59,10 +61,12 @@ describe Mongoid::Search do
|
|
59
61
|
|
60
62
|
it 'should leave utf8 characters' do
|
61
63
|
expect(@product._keywords).to eq %w[amazing awesome ole процессор процессоры эльбрус]
|
64
|
+
expect(@product._unit_keywords).to eq %w[kilogram ole]
|
62
65
|
end
|
63
66
|
|
64
67
|
it "should return results in search when case doesn't match" do
|
65
68
|
expect(Product.full_text_search('ЭЛЬБРУС').size).to eq 1
|
69
|
+
expect(Product.full_text_search('KILOGRAM', index: :_unit_keywords).size).to eq 1
|
66
70
|
end
|
67
71
|
end
|
68
72
|
|
@@ -74,15 +78,18 @@ describe Mongoid::Search do
|
|
74
78
|
end
|
75
79
|
|
76
80
|
it 'should validate keywords' do
|
77
|
-
product = Product.create brand: 'Apple', name: 'iPhone'
|
81
|
+
product = Product.create brand: 'Apple', name: 'iPhone', unit: 'box'
|
78
82
|
expect(product._keywords).to eq(%w[apple iphone])
|
83
|
+
expect(product._unit_keywords).to eq(%w[box])
|
79
84
|
end
|
80
85
|
end
|
81
86
|
|
82
87
|
it 'should set the _keywords field for array fields also' do
|
83
88
|
@product.attrs = ['lightweight', 'plastic', :red]
|
89
|
+
@product.measures = ['box', 'bunch', :bag]
|
84
90
|
@product.save!
|
85
91
|
expect(@product._keywords).to include 'lightweight', 'plastic', 'red'
|
92
|
+
expect(@product._unit_keywords).to include 'box', 'bunch', 'bag'
|
86
93
|
end
|
87
94
|
|
88
95
|
it 'should inherit _keywords field and build upon' do
|
@@ -91,39 +98,48 @@ describe Mongoid::Search do
|
|
91
98
|
tags: %w[Amazing Awesome Olé].map { |tag| Tag.new(name: tag) },
|
92
99
|
category: Category.new(name: 'Mobile'),
|
93
100
|
subproducts: [Subproduct.new(brand: 'Apple', name: 'Craddle')],
|
94
|
-
color: :white
|
101
|
+
color: :white,
|
102
|
+
size: :big
|
95
103
|
expect(variant._keywords).to include 'white'
|
104
|
+
expect(variant._unit_keywords).to include 'big'
|
96
105
|
expect(Variant.full_text_search(name: 'Apple', color: :white)).to eq [variant]
|
106
|
+
expect(Variant.full_text_search({ size: 'big' }, index: :_unit_keywords)).to eq [variant]
|
97
107
|
end
|
98
108
|
|
99
109
|
it 'should expand the ligature to ease searching' do
|
100
110
|
# ref: http://en.wikipedia.org/wiki/Typographic_ligature, only for french right now. Rules for other languages are not know
|
101
111
|
variant1 = Variant.create tags: ['œuvre'].map { |tag| Tag.new(name: tag) }
|
102
112
|
variant2 = Variant.create tags: ['æquo'].map { |tag| Tag.new(name: tag) }
|
113
|
+
variant3 = Variant.create measures: ['ꜵquo'].map { |measure| measure }
|
103
114
|
|
104
115
|
expect(Variant.full_text_search('œuvre')).to eq [variant1]
|
105
116
|
expect(Variant.full_text_search('oeuvre')).to eq [variant1]
|
106
117
|
expect(Variant.full_text_search('æquo')).to eq [variant2]
|
107
118
|
expect(Variant.full_text_search('aequo')).to eq [variant2]
|
119
|
+
expect(Variant.full_text_search('aoquo', index: :_unit_keywords)).to eq [variant3]
|
120
|
+
expect(Variant.full_text_search('ꜵquo', index: :_unit_keywords)).to eq [variant3]
|
108
121
|
end
|
109
122
|
|
110
|
-
it 'should set the
|
123
|
+
it 'should set the keywords fields with stemmed words if stem is enabled' do
|
111
124
|
Mongoid::Search.stem_keywords = true
|
112
125
|
@product.save!
|
113
126
|
expect(@product._keywords.sort).to eq %w[amaz appl awesom craddl iphon mobil review ol info descript summari].sort
|
127
|
+
expect(@product._unit_keywords.sort).to eq %w[mobil awesom ol].sort
|
114
128
|
end
|
115
129
|
|
116
|
-
it 'should set the
|
130
|
+
it 'should set the keywords fields with custom stemmed words if stem is enabled with a custom lambda' do
|
117
131
|
Mongoid::Search.stem_keywords = true
|
118
132
|
Mongoid::Search.stem_proc = proc { |word| word.upcase }
|
119
133
|
@product.save!
|
120
134
|
expect(@product._keywords.sort).to eq %w[AMAZING APPLE AWESOME CRADDLE DESCRIPTION INFO IPHONE MOBILE OLE REVIEWS SUMMARY]
|
135
|
+
expect(@product._unit_keywords.sort).to eq %w[AWESOME MOBILE OLE]
|
121
136
|
end
|
122
137
|
|
123
138
|
it 'should ignore keywords in an ignore list' do
|
124
139
|
Mongoid::Search.ignore_list = YAML.safe_load(File.open(File.dirname(__FILE__) + '/config/ignorelist.yml'))['ignorelist']
|
125
140
|
@product.save!
|
126
141
|
expect(@product._keywords.sort).to eq %w[apple craddle iphone mobile reviews ole info description summary].sort
|
142
|
+
expect(@product._unit_keywords.sort).to eq %w[mobile ole].sort
|
127
143
|
end
|
128
144
|
|
129
145
|
it 'should incorporate numbers as keywords' do
|
@@ -205,7 +221,7 @@ describe Mongoid::Search do
|
|
205
221
|
end
|
206
222
|
|
207
223
|
it 'should have a method to index keywords' do
|
208
|
-
expect(@product.index_keywords!).to
|
224
|
+
expect(@product.index_keywords!).to include(true)
|
209
225
|
end
|
210
226
|
|
211
227
|
it 'should have a class method to index all documents keywords' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid_search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mauricio Zaffari
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fast-stemmer
|
@@ -140,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
140
|
version: 1.3.6
|
141
141
|
requirements: []
|
142
142
|
rubyforge_project:
|
143
|
-
rubygems_version: 2.6.
|
143
|
+
rubygems_version: 2.6.14
|
144
144
|
signing_key:
|
145
145
|
specification_version: 4
|
146
146
|
summary: Search implementation for Mongoid ORM
|