mongoid_search 0.3.5 → 0.3.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 790663a1de866f407ace368cc503cd724cf4ffc6
4
- data.tar.gz: f95fc5e91b0eb1b12eb95a60bd9c57688ae12bb7
3
+ metadata.gz: 65d13fcd90c890df7b15f2175b701e951259f8de
4
+ data.tar.gz: '097843e60c25fc38ddb96789093dc798a08c5739'
5
5
  SHA512:
6
- metadata.gz: ec1fd1b237c921939f66ca1b7a719f13a1275a19f42e86ef72f368ae7396b21c5fa6ab97e090a070ae656b45bccdaf6607e369a82754e9bfec828f2bca3a1c43
7
- data.tar.gz: 3af9e42610b204de4a78e802bd3efaff38cabfa8a53a1f82b7af191cb9fe31e823e203f3087b606efe2d6fea38b0deb92b3751d2ab49674b410df06b1b40fb31
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.5
1
+ 0.3.6
@@ -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, _options = args_and_options(args)
18
- self.search_fields = (search_fields || []).concat args
17
+ args, options = args_and_options(args)
18
+ set_search_fields(options[:index], args)
19
19
 
20
- field :_keywords, type: Array
20
+ field options[:index], type: Array
21
21
 
22
- index({ _keywords: 1 }, background: true)
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
- { _keywords: kw }
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._keywords) {
103
- if(this._keywords[j] == keywords[i]) {
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
- update_attribute(:_keywords, set_keywords)
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
- self._keywords = Mongoid::Search::Util.keywords(self, search_fields)
130
- .flatten.reject { |k| k.nil? || k.empty? }.uniq.sort
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
@@ -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
@@ -1,5 +1,7 @@
1
1
  autoload :Product, 'models/product.rb'
2
2
  class Variant < Product
3
3
  field :color
4
+ field :size
4
5
  search_in :color
6
+ search_in :size, index: :_unit_keywords
5
7
  end
@@ -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 _keywords field with stemmed words if stem is enabled' do
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 _keywords field with custom stemmed words if stem is enabled with a custom lambda' do
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 eq true
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.5
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-02-07 00:00:00.000000000 Z
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.12
143
+ rubygems_version: 2.6.14
144
144
  signing_key:
145
145
  specification_version: 4
146
146
  summary: Search implementation for Mongoid ORM