mongoid_search 0.3.4 → 0.3.5

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: 832d506c4a4b192adabbc3858899481804da533e
4
- data.tar.gz: ee2c35e2dc25e5de7cc7bb02c149260ff487ff04
3
+ metadata.gz: 790663a1de866f407ace368cc503cd724cf4ffc6
4
+ data.tar.gz: f95fc5e91b0eb1b12eb95a60bd9c57688ae12bb7
5
5
  SHA512:
6
- metadata.gz: 7f40a5e5437f1865b71bd929ff3c861c33f35197e5c561bfaff6d0ffd31671983c1c0c5699ccbe0f9fb9af7c3af253ff9b704f6b93c186be8c13168ea6dc03b4
7
- data.tar.gz: 63e5ee87ed079f03373951efc4cc6eb6accf13cf48ab4e8f53b76bcd689fb04bb097fbe2a2e66db6eccd71438db0876b4abd1f8e61608d23ff37aabc92a3eb8c
6
+ metadata.gz: ec1fd1b237c921939f66ca1b7a719f13a1275a19f42e86ef72f368ae7396b21c5fa6ab97e090a070ae656b45bccdaf6607e369a82754e9bfec828f2bca3a1c43
7
+ data.tar.gz: 3af9e42610b204de4a78e802bd3efaff38cabfa8a53a1f82b7af191cb9fe31e823e203f3087b606efe2d6fea38b0deb92b3751d2ab49674b410df06b1b40fb31
data/README.md CHANGED
@@ -1,177 +1,190 @@
1
- Mongoid Search
2
- ============
1
+ # Mongoid Search
3
2
 
4
- Mongoid Search is a simple full text search implementation for Mongoid ORM. It performs well for small data sets. If your searchable model is big (i.e. 1.000.000+ records), solr or sphinx may suit you better.
3
+ Mongoid Search is a simple full text search implementation for Mongoid ORM. It supports Mongoid 3, 4, 5 and 6 and performs well for small data sets. If your searchable model is big (i.e. 1.000.000+ records), [mongoid_fulltext](https://github.com/mongoid/mongoid_fulltext), ElasticSearch, Solr or Sphinx may suit you better.
5
4
 
6
- Installation
7
- --------
5
+ [![Build Status](https://travis-ci.org/mongoid/mongoid_search.svg?branch=master)](https://travis-ci.org/mongoid/mongoid_search)
8
6
 
9
- In your Gemfile:
10
-
11
- gem 'mongoid_search'
7
+ ## Installation
12
8
 
13
- If your project is still using mongoid 2.x.x, stick to mongoid_search 0.2.x:
9
+ In your Gemfile:
14
10
 
15
- gem 'mongoid_search', '~> 0.2.8'
11
+ ```ruby
12
+ gem 'mongoid_search'
13
+ ```
16
14
 
17
15
  Then:
18
16
 
19
- bundle install
17
+ ```
18
+ bundle install
19
+ ```
20
20
 
21
- Examples
22
- --------
21
+ ## Examples
23
22
 
24
- class Product
25
- include Mongoid::Document
26
- include Mongoid::Search
27
- field :brand
28
- field :name
29
- field :info, :type => Hash
23
+ ```ruby
24
+ class Product
25
+ include Mongoid::Document
26
+ include Mongoid::Search
27
+ field :brand
28
+ field :name
29
+ field :info, type: Hash
30
30
 
31
- has_many :tags
32
- belongs_to :category
31
+ has_many :tags
32
+ belongs_to :category
33
33
 
34
- search_in :brand, :name, :tags => :name, :category => :name, :info => [:summary, :description]
35
- end
34
+ search_in :brand, :name, tags: :name, category: :name, info: %i[summary description]
35
+ end
36
36
 
37
- class Tag
38
- include Mongoid::Document
39
- field :name
37
+ class Tag
38
+ include Mongoid::Document
39
+ field :name
40
40
 
41
- belongs_to :product
42
- end
41
+ belongs_to :product
42
+ end
43
43
 
44
- class Category
45
- include Mongoid::Document
46
- field :name
44
+ class Category
45
+ include Mongoid::Document
46
+ field :name
47
47
 
48
- has_many :products
49
- end
48
+ has_many :products
49
+ end
50
+ ```
50
51
 
51
- Now when you save a product, you get a _keywords field automatically:
52
+ Now when you save a product, you get a `_keywords` field automatically:
52
53
 
53
- p = Product.new :brand => "Apple", :name => "iPhone", :info => {:summary => "Info-summary", :description => "Info-description"}
54
- p.tags << Tag.new(:name => "Amazing")
55
- p.tags << Tag.new(:name => "Awesome")
56
- p.tags << Tag.new(:name => "Superb")
57
- p.save
58
- => true
59
- p._keywords
60
- => ["amazing", "apple", "awesome", "iphone", "superb", "Info-summary", "Info-description"]
54
+ ```ruby
55
+ p = Product.new brand: 'Apple', name: 'iPhone', info: { summary: 'Info-summary', description: 'Info-description' }
56
+ p.tags << Tag.new(name: 'Amazing')
57
+ p.tags << Tag.new(name: 'Awesome')
58
+ p.tags << Tag.new(name: 'Superb')
59
+ p.save
60
+ # => true
61
+ p._keywords
62
+ # => ["amazing", "apple", "awesome", "iphone", "superb", "Info-summary", "Info-description"]
63
+ ```
61
64
 
62
- Now you can run search, which will look in the _keywords field and return all matching results:
65
+ Now you can run search, which will look in the `_keywords` field and return all matching results:
63
66
 
64
- Product.full_text_search("apple iphone").size
65
- => 1
67
+ ```ruby
68
+ Product.full_text_search("apple iphone").size
69
+ # => 1
70
+ ```
66
71
 
67
72
  Note that the search is case insensitive, and accept partial searching too:
68
73
 
69
- Product.full_text_search("ipho").size
70
- => 1
74
+ ```ruby
75
+ Product.full_text_search('ipho').size
76
+ # => 1
77
+ ```
71
78
 
72
- Assuming you have a category with multiple products you can use the following
73
- code to search for 'iphone' in products cheaper than $499
79
+ Assuming you have a category with multiple products you can use the following code to search for 'iphone' in products cheaper than $499.
74
80
 
75
- @category.products.where(:price.lt => 499).full_text_search('iphone').asc(:price)
81
+ ```ruby
82
+ category.products.where(:price.lt => 499).full_text_search('iphone').asc(:price)
83
+ ```
76
84
 
77
85
  To index or reindex all existing records, run this rake task
78
86
 
79
- $ rake mongoid_search:index
80
-
81
- Options
82
- -------
83
-
84
- match:
85
-
86
- _:any_ - match any occurrence
87
+ ```
88
+ $ rake mongoid_search:index
89
+ ```
87
90
 
88
- _:all_ - match all ocurrences
91
+ ## Options
89
92
 
90
- Default is _:any_.
93
+ ### match
91
94
 
92
- Product.full_text_search("apple motorola", match: :any).size
93
- => 1
95
+ * `:any` - match any occurrence
96
+ * `:all` - match all occurrences
94
97
 
95
- Product.full_text_search("apple motorola", match: :all).size
96
- => 0
98
+ Default is `:any`.
97
99
 
98
- allow\_empty\_search:
100
+ ```ruby
101
+ Product.full_text_search('apple motorola', match: :any).size
102
+ # => 1
99
103
 
100
- _true_ - will return Model.all
104
+ Product.full_text_search('apple motorola', match: :all).size
105
+ # => 0
106
+ ```
101
107
 
102
- _false_ - will return []
108
+ ### allow\_empty\_search
103
109
 
104
- Default is _false_.
110
+ * `true` - will return `Model.all`
111
+ * `false` - will return `[]`
105
112
 
106
- Product.full_text_search("", allow_empty_search: true).size
107
- => 1
113
+ Default is `false`.
108
114
 
109
- relevant_search:
115
+ ```ruby
116
+ Product.full_text_search('', allow_empty_search: true).size
117
+ # => 1
118
+ ```
110
119
 
111
- _true_ - Adds relevance information to the results
120
+ ### relevant_search
112
121
 
113
- _false_ - No relevance information
122
+ * `true` - adds relevance information to the results
123
+ * `false` - no relevance information
114
124
 
115
- Default is _false_.
125
+ Default is `false`.
116
126
 
117
- Product.full_text_search('amazing apple', relevant_search: true)
118
- => [#<Product _id: 5016e7d16af54efe1c000001, _type: nil, brand: "Apple", name: "iPhone", attrs: nil, info: nil, category_id: nil, _keywords: ["amazing", "apple", "awesome", "iphone", "superb"], relevance: 2.0>]
127
+ ```ruby
128
+ Product.full_text_search('amazing apple', relevant_search: true)
129
+ # => [#<Product _id: 5016e7d16af54efe1c000001, _type: nil, brand: "Apple", name: "iPhone", attrs: nil, info: nil, category_id: nil, _keywords: ["amazing", "apple", "awesome", "iphone", "superb"], relevance: 2.0>]
130
+ ```
119
131
 
120
- 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.
132
+ 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.
121
133
 
122
- Initializer
123
- -----------
134
+ ## Initializer
124
135
 
125
136
  Alternatively, you can create an initializer to setup those options:
126
137
 
127
- Mongoid::Search.setup do |config|
128
- ## Default matching type. Match :any or :all searched keywords
129
- config.match = :any
138
+ ```ruby
139
+ Mongoid::Search.setup do |config|
140
+ ## Default matching type. Match :any or :all searched keywords
141
+ config.match = :any
130
142
 
131
- ## If true, an empty search will return all objects
132
- config.allow_empty_search = false
143
+ ## If true, an empty search will return all objects
144
+ config.allow_empty_search = false
133
145
 
134
- ## If true, will search with relevance information
135
- config.relevant_search = false
146
+ ## If true, will search with relevance information
147
+ config.relevant_search = false
136
148
 
137
- ## Stem keywords
138
- config.stem_keywords = false
149
+ ## Stem keywords
150
+ config.stem_keywords = false
139
151
 
140
- ## Add a custom proc returning strings to replace the default stemmer
141
- # For example using ruby-stemmer:
142
- # config.stem_proc = Proc.new { |word| Lingua.stemmer(word, :language => 'nl') }
152
+ ## Add a custom proc returning strings to replace the default stemmer
153
+ # For example using ruby-stemmer:
154
+ # config.stem_proc = Proc.new { |word| Lingua.stemmer(word, :language => 'nl') }
143
155
 
144
- ## Words to ignore
145
- config.ignore_list = []
156
+ ## Words to ignore
157
+ config.ignore_list = []
146
158
 
147
- ## An array of words
148
- # config.ignore_list = %w{ a an to from as }
159
+ ## An array of words
160
+ # config.ignore_list = %w{ a an to from as }
149
161
 
150
- ## Or from a file
151
- # config.ignore_list = YAML.load(File.open(File.dirname(__FILE__) + '/config/ignorelist.yml'))["ignorelist"]
162
+ ## Or from a file
163
+ # config.ignore_list = YAML.load(File.open(File.dirname(__FILE__) + '/config/ignorelist.yml'))["ignorelist"]
152
164
 
153
- ## Search using regex (slower)
154
- config.regex_search = true
165
+ ## Search using regex (slower)
166
+ config.regex_search = true
155
167
 
156
- ## Regex to search
168
+ ## Regex to search
157
169
 
158
- ## Match partial words on both sides (slower)
159
- config.regex = Proc.new { |query| /#{query}/ }
170
+ ## Match partial words on both sides (slower)
171
+ config.regex = Proc.new { |query| /#{query}/ }
160
172
 
161
- ## Match partial words on the beginning or in the end (slightly faster)
162
- # config.regex = Proc.new { |query| /^#{query}/ }
163
- # config.regex = Proc.new { |query| /#{query}$/ }
173
+ ## Match partial words on the beginning or in the end (slightly faster)
174
+ # config.regex = Proc.new { |query| /^#{query}/ }
175
+ # config.regex = Proc.new { |query| /#{query}$/ }
164
176
 
165
- # Ligatures to be replaced
166
- # http://en.wikipedia.org/wiki/Typographic_ligature
167
- config.ligatures = { "œ"=>"oe", "æ"=>"ae" }
177
+ # Ligatures to be replaced
178
+ # http://en.wikipedia.org/wiki/Typographic_ligature
179
+ config.ligatures = { "œ"=>"oe", "æ"=>"ae" }
168
180
 
169
- # Strip symbols regex to be replaced. These symbols will be replaced by space
170
- config.strip_symbols = /[._:;'\"`,?|+={}()!@#%^&*<>~\$\-\\\/\[\]]/
181
+ # Strip symbols regex to be replaced. These symbols will be replaced by space
182
+ config.strip_symbols = /[._:;'\"`,?|+={}()!@#%^&*<>~\$\-\\\/\[\]]/
171
183
 
172
- # Strip accents regex to be replaced. These sybols will be removed after strip_symbols replacing
173
- config.strip_accents = /[^\s\p{Alnum}]/
184
+ # Strip accents regex to be replaced. These sybols will be removed after strip_symbols replacing
185
+ config.strip_accents = /[^\s\p{Alnum}]/
174
186
 
175
- # Minimum word size. Words smaller than it won't be indexed
176
- config.minimum_word_size = 2
177
- end
187
+ # Minimum word size. Words smaller than it won't be indexed
188
+ config.minimum_word_size = 2
189
+ end
190
+ ```
data/Rakefile CHANGED
@@ -3,8 +3,11 @@ require 'rake'
3
3
 
4
4
  require 'rspec/core/rake_task'
5
5
  RSpec::Core::RakeTask.new(:spec) do |spec|
6
- spec.rspec_opts = ["-c", "-f progress"]
6
+ spec.rspec_opts = ['-c', '-f progress']
7
7
  spec.pattern = 'spec/**/*_spec.rb'
8
8
  end
9
9
 
10
- task :default => :spec
10
+ require 'rubocop/rake_task'
11
+ RuboCop::RakeTask.new(:rubocop)
12
+
13
+ task default: %i[rubocop spec]
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.4
1
+ 0.3.5
@@ -1,10 +1,6 @@
1
- # encoding: utf-8
2
-
3
1
  require 'mongoid_search/mongoid_search'
4
2
 
5
- if defined?(Rails)
6
- require 'mongoid_search/railtie'
7
- end
3
+ require 'mongoid_search/railtie' if defined?(Rails)
8
4
 
9
5
  module Mongoid::Search
10
6
  ## Default matching type. Match :any or :all searched keywords
@@ -25,7 +21,7 @@ module Mongoid::Search
25
21
 
26
22
  ## Stem procedure
27
23
  mattr_accessor :stem_proc
28
- @@stem_proc = Proc.new { |word| word.stem }
24
+ @@stem_proc = proc { |word| word.stem }
29
25
 
30
26
  ## Words to ignore
31
27
  mattr_accessor :ignore_list
@@ -45,7 +41,7 @@ module Mongoid::Search
45
41
  mattr_accessor :regex
46
42
 
47
43
  ## Match partial words on both sides (slower)
48
- @@regex = Proc.new { |query| /#{query}/ }
44
+ @@regex = proc { |query| /#{query}/ }
49
45
 
50
46
  ## Match partial words on the beginning or in the end (slightly faster)
51
47
  # @@regex = Proc.new { |query| /^#{query}/ }
@@ -54,7 +50,7 @@ module Mongoid::Search
54
50
  # Ligatures to be replaced
55
51
  # http://en.wikipedia.org/wiki/Typographic_ligature
56
52
  mattr_accessor :ligatures
57
- @@ligatures = { "œ"=>"oe", "æ"=>"ae" }
53
+ @@ligatures = { 'œ' => 'oe', 'æ' => 'ae' }
58
54
 
59
55
  # Minimum word size. Words smaller than it won't be indexed
60
56
  mattr_accessor :minimum_word_size
@@ -14,7 +14,8 @@ class Mongoid::Search::Log
14
14
  end
15
15
 
16
16
  private
17
+
17
18
  def self.colorize(text, code)
18
19
  "\033[#{code}m#{text}\033[0m"
19
20
  end
20
- end
21
+ end
@@ -15,16 +15,16 @@ module Mongoid::Search
15
15
  # Set a field or a number of fields as sources for search
16
16
  def search_in(*args)
17
17
  args, _options = args_and_options(args)
18
- self.search_fields = (self.search_fields || []).concat args
18
+ self.search_fields = (search_fields || []).concat args
19
19
 
20
- field :_keywords, :type => Array
20
+ field :_keywords, type: Array
21
21
 
22
- index({ :_keywords => 1 }, { :background => true })
22
+ index({ _keywords: 1 }, background: true)
23
23
 
24
24
  before_save :set_keywords
25
25
  end
26
26
 
27
- def full_text_search(query, options={})
27
+ def full_text_search(query, options = {})
28
28
  options = extract_options(options)
29
29
  attr_accessor :relevance if options[:relevant_search].eql? true
30
30
 
@@ -44,34 +44,37 @@ module Mongoid::Search
44
44
  # Goes through all documents in the class that includes Mongoid::Search
45
45
  # and indexes the keywords.
46
46
  def index_keywords!
47
- all.each { |d| d.index_keywords! ? Log.green(".") : Log.red("F") }
47
+ all.each { |d| d.index_keywords! ? Log.green('.') : Log.red('F') }
48
48
  end
49
49
 
50
50
  private
51
51
 
52
52
  def query(keywords, options)
53
53
  keywords_hash = keywords.map do |kw|
54
- kw = Mongoid::Search.regex.call(kw) if Mongoid::Search.regex_search
55
- { :_keywords => kw }
54
+ if Mongoid::Search.regex_search
55
+ escaped_kw = Regexp.escape(kw)
56
+ kw = Mongoid::Search.regex.call(escaped_kw)
57
+ end
58
+ { _keywords: kw }
56
59
  end
57
60
 
58
- criteria.send("#{(options[:match]).to_s}_of", *keywords_hash)
61
+ criteria.send("#{(options[:match])}_of", *keywords_hash)
59
62
  end
60
63
 
61
64
  def args_and_options(args)
62
65
  options = args.last.is_a?(Hash) &&
63
- [:match,
64
- :allow_empty_search,
65
- :relevant_search].include?(args.last.keys.first) ? args.pop : {}
66
+ %i[match
67
+ allow_empty_search
68
+ relevant_search].include?(args.last.keys.first) ? args.pop : {}
66
69
 
67
70
  [args, extract_options(options)]
68
71
  end
69
72
 
70
73
  def extract_options(options)
71
74
  {
72
- :match => options[:match] || Mongoid::Search.match,
73
- :allow_empty_search => options[:allow_empty_search] || Mongoid::Search.allow_empty_search,
74
- :relevant_search => options[:relevant_search] || Mongoid::Search.relevant_search
75
+ match: options[:match] || Mongoid::Search.match,
76
+ allow_empty_search: options[:allow_empty_search] || Mongoid::Search.allow_empty_search,
77
+ relevant_search: options[:relevant_search] || Mongoid::Search.relevant_search
75
78
  }
76
79
  end
77
80
 
@@ -81,20 +84,18 @@ module Mongoid::Search
81
84
 
82
85
  def search_relevant(query, options)
83
86
  results_with_relevance(query, options).sort { |o| o['value'] }.map do |r|
84
-
85
- new(r['_id'].merge(:relevance => r['value'])) do |o|
87
+ new(r['_id'].merge(relevance: r['value'])) do |o|
86
88
  # Need to match the actual object
87
89
  o.instance_variable_set('@new_record', false)
88
90
  o._id = r['_id']['_id']
89
91
  end
90
-
91
92
  end
92
93
  end
93
94
 
94
95
  def results_with_relevance(query, options)
95
96
  keywords = Mongoid::Search::Util.normalize_keywords(query)
96
97
 
97
- map = %Q{
98
+ map = %{
98
99
  function() {
99
100
  var entries = 0;
100
101
  for(i in keywords) {
@@ -110,13 +111,13 @@ module Mongoid::Search
110
111
  }
111
112
  }
112
113
 
113
- reduce = %Q{
114
+ reduce = %{
114
115
  function(key, values) {
115
116
  return(values);
116
117
  }
117
118
  }
118
119
 
119
- query(keywords, options).map_reduce(map, reduce).scope(:keywords => keywords).out(:inline => 1)
120
+ query(keywords, options).map_reduce(map, reduce).scope(keywords: keywords).out(inline: 1)
120
121
  end
121
122
  end
122
123
 
@@ -125,7 +126,7 @@ module Mongoid::Search
125
126
  end
126
127
 
127
128
  def set_keywords
128
- self._keywords = Mongoid::Search::Util.keywords(self, self.search_fields).
129
- flatten.reject{|k| k.nil? || k.empty?}.uniq.sort
129
+ self._keywords = Mongoid::Search::Util.keywords(self, search_fields)
130
+ .flatten.reject { |k| k.nil? || k.empty? }.uniq.sort
130
131
  end
131
132
  end