mongoid_search 0.2.3 → 0.2.4
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.
- data/README.md +22 -1
- data/lib/mongoid_search/mongoid_search.rb +23 -13
- data/lib/mongoid_search/util.rb +2 -2
- data/spec/models/product.rb +2 -1
- data/spec/models/variant.rb +4 -0
- data/spec/mongoid_search_spec.rb +33 -3
- data/spec/util_spec.rb +4 -0
- metadata +5 -3
data/README.md
CHANGED
@@ -62,6 +62,15 @@ Note that the search is case insensitive, and accept partial searching too:
|
|
62
62
|
|
63
63
|
Product.search("ipho").size
|
64
64
|
=> 1
|
65
|
+
|
66
|
+
Assuming you have a category with multiple products you can now use the following
|
67
|
+
code to search for 'iphone' in products cheaper than $499
|
68
|
+
|
69
|
+
@category.products.where(:price.lt => 499).asc(:price).csearch('iphone')
|
70
|
+
|
71
|
+
In this case we have to use csearch, an alias for search, because since v2.0.0
|
72
|
+
Mongoid defines it's own Criteria.search method.
|
73
|
+
|
65
74
|
|
66
75
|
Options
|
67
76
|
-------
|
@@ -90,11 +99,23 @@ allow_empty_search:
|
|
90
99
|
|
91
100
|
Product.search("").size
|
92
101
|
=> 1
|
102
|
+
|
103
|
+
ignore_list:
|
104
|
+
Pass in an ignore list location. Keywords in that list will be ignored.
|
105
|
+
|
106
|
+
search_in :brand, :name, { :tags => :name }, { :ignore_list => Rails.root.join("config", "ignorelist.yml") }
|
107
|
+
|
108
|
+
The list should look like:
|
109
|
+
|
110
|
+
ignorelist:
|
111
|
+
a, an, to, from, as
|
112
|
+
|
113
|
+
You can include how many keywords you like.
|
93
114
|
|
94
115
|
TODO
|
95
116
|
----
|
96
117
|
|
97
118
|
* Strip html with sanitize (https://github.com/rgrove/sanitize)
|
98
|
-
*
|
119
|
+
* Rewrite and test relevant search
|
99
120
|
* Move all configurations to a configuration file. Maybe /config/mongoid_search.yml.
|
100
121
|
|
@@ -14,7 +14,7 @@ module Mongoid::Search
|
|
14
14
|
self.relevant_search = [true, false].include?(options[:relevant_search]) ? options[:allow_empty_search] : false
|
15
15
|
self.stem_keywords = [true, false].include?(options[:stem_keywords]) ? options[:allow_empty_search] : false
|
16
16
|
self.ignore_list = YAML.load(File.open(options[:ignore_list]))["ignorelist"] if options[:ignore_list].present?
|
17
|
-
self.search_fields = args
|
17
|
+
self.search_fields = (self.search_fields || []).concat args
|
18
18
|
|
19
19
|
field :_keywords, :type => Array
|
20
20
|
index :_keywords
|
@@ -29,14 +29,20 @@ module Mongoid::Search
|
|
29
29
|
search_without_relevance(query, options)
|
30
30
|
end
|
31
31
|
end
|
32
|
+
|
33
|
+
# Mongoid 2.0.0 introduces Criteria.seach so we need to provide
|
34
|
+
# alternate method
|
35
|
+
alias csearch search
|
32
36
|
|
33
37
|
def search_without_relevance(query, options={})
|
34
|
-
return
|
35
|
-
|
38
|
+
return criteria.all if query.blank? && allow_empty_search
|
39
|
+
criteria.send("#{(options[:match]||self.match).to_s}_in", :_keywords => Util.keywords(query, stem_keywords, ignore_list).map { |q| /#{q}/ })
|
36
40
|
end
|
37
|
-
|
41
|
+
|
42
|
+
# I know what this method should do, but I don't really know what it does.
|
43
|
+
# It was a pull from another fork, with no tests on it. Proably should be rewrited (and tested).
|
38
44
|
def search_relevant(query, options={})
|
39
|
-
return
|
45
|
+
return criteria.all if query.blank? && allow_empty_search
|
40
46
|
|
41
47
|
keywords = Util.keywords(query, stem_keywords, ignore_list)
|
42
48
|
|
@@ -64,7 +70,7 @@ module Mongoid::Search
|
|
64
70
|
{:_keywords => kw}
|
65
71
|
end
|
66
72
|
|
67
|
-
criteria = self.any_of(*kw_conditions)
|
73
|
+
criteria = (criteria || self).any_of(*kw_conditions)
|
68
74
|
|
69
75
|
query = criteria.selector
|
70
76
|
|
@@ -72,15 +78,15 @@ module Mongoid::Search
|
|
72
78
|
options.delete(:skip)
|
73
79
|
options.merge! :scope => {:keywords => keywords}, :query => query
|
74
80
|
|
75
|
-
res = collection.map_reduce(map, reduce, options)
|
76
|
-
|
77
|
-
|
81
|
+
# res = collection.map_reduce(map, reduce, options)
|
82
|
+
# res.find.sort(['value', -1]) # Cursor
|
83
|
+
collection.map_reduce(map, reduce, options)
|
78
84
|
end
|
79
85
|
end
|
80
86
|
|
81
87
|
private
|
82
88
|
|
83
|
-
# TODO: This need some
|
89
|
+
# TODO: This need some refactoring..
|
84
90
|
def set_keywords
|
85
91
|
self._keywords = self.search_fields.map do |field|
|
86
92
|
if field.is_a?(Hash)
|
@@ -98,9 +104,13 @@ module Mongoid::Search
|
|
98
104
|
end
|
99
105
|
end
|
100
106
|
else
|
101
|
-
|
102
|
-
|
107
|
+
value = self[field]
|
108
|
+
if value.is_a?(Array)
|
109
|
+
value.each {|v| Util.keywords(v, stem_keywords, ignore_list) if v}
|
110
|
+
else
|
111
|
+
Util.keywords(value, stem_keywords, ignore_list) if value
|
112
|
+
end
|
103
113
|
end
|
104
|
-
end.flatten.
|
114
|
+
end.flatten.map(&:to_s).select{|f| not f.empty? }.uniq.sort
|
105
115
|
end
|
106
116
|
end
|
data/lib/mongoid_search/util.rb
CHANGED
@@ -2,12 +2,12 @@ module Util
|
|
2
2
|
|
3
3
|
def self.keywords(text, stem_keywords, ignore_list)
|
4
4
|
return [] if text.blank?
|
5
|
-
text = text.
|
5
|
+
text = text.to_s.
|
6
6
|
mb_chars.
|
7
7
|
normalize(:kd).
|
8
8
|
to_s.
|
9
9
|
gsub(/[._:;'"`,?|+={}()!@#%^&*<>~\$\-\\\/\[\]]/, ' '). # strip punctuation
|
10
|
-
gsub(/[^[:
|
10
|
+
gsub(/[^[:alnum:]\s]/,''). # strip accents
|
11
11
|
downcase.
|
12
12
|
split(' ').
|
13
13
|
reject { |word| word.size < 2 }
|
data/spec/models/product.rb
CHANGED
@@ -3,10 +3,11 @@ class Product
|
|
3
3
|
include Mongoid::Search
|
4
4
|
field :brand
|
5
5
|
field :name
|
6
|
+
field :attrs, :type => Array
|
6
7
|
|
7
8
|
references_many :tags
|
8
9
|
referenced_in :category
|
9
10
|
embeds_many :subproducts
|
10
11
|
|
11
|
-
search_in :brand, :name, :outlet, :tags => :name, :category => :name, :subproducts => [:brand, :name]
|
12
|
+
search_in :brand, :name, :outlet, :attrs, :tags => :name, :category => :name, :subproducts => [:brand, :name]
|
12
13
|
end
|
data/spec/mongoid_search_spec.rb
CHANGED
@@ -31,21 +31,45 @@ describe Mongoid::Search do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it "should set the _keywords field" do
|
34
|
-
@product.
|
34
|
+
@product.attrs = ['lightweight', 'rugged', :red]
|
35
|
+
@product.save!
|
36
|
+
@product._keywords.should include "amazing", "apple", "awesome", "craddle", "iphone", "mobile", "ole", "lightweight", "rugged", "red"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should inherit _keywords field and build upon" do
|
40
|
+
variant = Variant.create :brand => "Apple",
|
41
|
+
:name => "iPhone",
|
42
|
+
:tags => ["Amazing", "Awesome", "Olé"].map { |tag| Tag.new(:name => tag) },
|
43
|
+
:category => Category.new(:name => "Mobile"),
|
44
|
+
:subproducts => [Subproduct.new(:brand => "Apple", :name => "Craddle")],
|
45
|
+
:color => :white
|
46
|
+
variant._keywords.should include "amazing", "apple", "awesome", "craddle", "iphone", "mobile", "ole", "white"
|
47
|
+
Variant.search(:name => 'Apple', :color => :white).size.should == 1
|
35
48
|
end
|
36
49
|
|
37
50
|
it "should set the _keywords field with stemmed words if stem is enabled" do
|
38
51
|
Product.stem_keywords = true
|
39
52
|
@product.save!
|
40
|
-
@product._keywords.should == ["amaz", "appl", "
|
53
|
+
@product._keywords.should == ["amaz", "appl", "awesom", "craddl", "iphon", "mobil", "ol"]
|
41
54
|
end
|
42
55
|
|
43
56
|
it "should ignore keywords in an ignore list" do
|
44
57
|
Product.ignore_list = YAML.load(File.open(File.dirname(__FILE__) + '/config/ignorelist.yml'))["ignorelist"]
|
45
58
|
@product.save!
|
46
|
-
@product._keywords.should == ["apple", "
|
59
|
+
@product._keywords.should == ["apple", "craddle", "iphone", "mobile", "ole"]
|
47
60
|
end
|
48
61
|
|
62
|
+
it "should incorporate numbers as keywords" do
|
63
|
+
@product = Product.create :brand => "Ford",
|
64
|
+
:name => "T 1908",
|
65
|
+
:tags => ["Amazing", "First", "Car"].map { |tag| Tag.new(:name => tag) },
|
66
|
+
:category => Category.new(:name => "Vehicle")
|
67
|
+
|
68
|
+
@product.save!
|
69
|
+
@product._keywords.should == ["1908","amazing", "car", "first", "ford", "vehicle"]
|
70
|
+
end
|
71
|
+
|
72
|
+
|
49
73
|
it "should return results in search" do
|
50
74
|
Product.search("apple").size.should == 1
|
51
75
|
end
|
@@ -99,4 +123,10 @@ describe Mongoid::Search do
|
|
99
123
|
it "should search for embedded documents" do
|
100
124
|
Product.search("craddle").size.should == 1
|
101
125
|
end
|
126
|
+
|
127
|
+
it 'should work in a chainable fashion' do
|
128
|
+
@product.category.products.where(:brand => 'Apple').csearch('apple').size.should == 1
|
129
|
+
@product.category.products.csearch('craddle').where(:brand => 'Apple').size.should == 1
|
130
|
+
end
|
131
|
+
|
102
132
|
end
|
data/spec/util_spec.rb
CHANGED
@@ -37,4 +37,8 @@ describe Util do
|
|
37
37
|
it "should ignore keywords with less than two words" do
|
38
38
|
Util.keywords("A runner running", false, "").should_not include "a"
|
39
39
|
end
|
40
|
+
|
41
|
+
it "should not ignore numbers" do
|
42
|
+
Util.keywords("Ford T 1908", false, "").should include "1908"
|
43
|
+
end
|
40
44
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 4
|
9
|
+
version: 0.2.4
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Mauricio Zaffari
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-04-
|
17
|
+
date: 2011-04-14 00:00:00 -03:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -127,6 +127,7 @@ files:
|
|
127
127
|
- spec/models/product.rb
|
128
128
|
- spec/models/subproduct.rb
|
129
129
|
- spec/models/tag.rb
|
130
|
+
- spec/models/variant.rb
|
130
131
|
- spec/mongoid_search_spec.rb
|
131
132
|
- spec/spec_helper.rb
|
132
133
|
- spec/util_spec.rb
|
@@ -170,6 +171,7 @@ test_files:
|
|
170
171
|
- spec/models/product.rb
|
171
172
|
- spec/models/subproduct.rb
|
172
173
|
- spec/models/tag.rb
|
174
|
+
- spec/models/variant.rb
|
173
175
|
- spec/mongoid_search_spec.rb
|
174
176
|
- spec/spec_helper.rb
|
175
177
|
- spec/util_spec.rb
|