mongomapper_search 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/README.md +102 -0
- data/Rakefile +10 -0
- data/lib/mongomapper_search/query.rb +13 -0
- data/lib/mongomapper_search/search.rb +75 -0
- data/lib/mongomapper_search/util.rb +43 -0
- data/lib/mongomapper_search.rb +3 -0
- data/spec/models/category.rb +6 -0
- data/spec/models/product.rb +13 -0
- data/spec/models/subproduct.rb +7 -0
- data/spec/models/tag.rb +6 -0
- data/spec/models/variant.rb +4 -0
- data/spec/search_spec.rb +150 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/util_spec.rb +41 -0
- metadata +134 -0
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (C) 2011 by Mário Peixoto
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
20
|
+
|
21
|
+
|
22
|
+
Based on mongoid_search, Copyright by Mauricio Zaffari, 2009
|
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
MongoMapper Search
|
2
|
+
============
|
3
|
+
|
4
|
+
MongoMapper Search is a simple full text search implementation for MongoMapper ODM based on mongoid_search (https://github.com/mauriciozaffari/mongoid_search).
|
5
|
+
|
6
|
+
Installation
|
7
|
+
--------
|
8
|
+
|
9
|
+
In your Gemfile:
|
10
|
+
|
11
|
+
gem 'mongomapper_search'
|
12
|
+
|
13
|
+
Then:
|
14
|
+
|
15
|
+
bundle install
|
16
|
+
|
17
|
+
Examples
|
18
|
+
--------
|
19
|
+
|
20
|
+
class Product
|
21
|
+
include MongoMapper::Document
|
22
|
+
include MongoMapper::Search
|
23
|
+
key :brand, String
|
24
|
+
key :name, String
|
25
|
+
|
26
|
+
many :tags
|
27
|
+
belongs_to :category
|
28
|
+
|
29
|
+
search_in :brand, :name, :tags => :name, :category => :name
|
30
|
+
end
|
31
|
+
|
32
|
+
class Tag
|
33
|
+
include MongoMapper::Document
|
34
|
+
key :name, Stirng
|
35
|
+
|
36
|
+
belongs_to :product
|
37
|
+
end
|
38
|
+
|
39
|
+
class Category
|
40
|
+
include MongoMapper::Document
|
41
|
+
key :name, String
|
42
|
+
|
43
|
+
many :products
|
44
|
+
end
|
45
|
+
|
46
|
+
Now when you save a product, you get a _keywords field automatically:
|
47
|
+
|
48
|
+
p = Product.new :brand => "Apple", :name => "iPhone"
|
49
|
+
p.tags << Tag.new(:name => "Amazing")
|
50
|
+
p.tags << Tag.new(:name => "Awesome")
|
51
|
+
p.tags << Tag.new(:name => "Superb")
|
52
|
+
p.save
|
53
|
+
=> true
|
54
|
+
p._keywords
|
55
|
+
|
56
|
+
Now you can run search, which will look in the _keywords field and return all matching results:
|
57
|
+
|
58
|
+
Product.search("apple iphone").size
|
59
|
+
=> 1
|
60
|
+
|
61
|
+
Note that the search is case insensitive, and accept partial searching too:
|
62
|
+
|
63
|
+
Product.search("ipho").size
|
64
|
+
=> 1
|
65
|
+
|
66
|
+
You can use search in a chainable way:
|
67
|
+
|
68
|
+
Product.where(:brand => "Apple").search('iphone').sort(:price.asc)
|
69
|
+
|
70
|
+
|
71
|
+
Options
|
72
|
+
-------
|
73
|
+
|
74
|
+
match:
|
75
|
+
_:any_ - match any occurrence
|
76
|
+
_:all_ - match all ocurrences
|
77
|
+
Default is _:any_.
|
78
|
+
|
79
|
+
search_in :brand, :name, { :tags => :name }, { :match => :any }
|
80
|
+
|
81
|
+
Product.search("apple motorola").size
|
82
|
+
=> 1
|
83
|
+
|
84
|
+
search_in :brand, :name, { :tags => :name }, { :match => :all }
|
85
|
+
|
86
|
+
Product.search("apple motorola").size
|
87
|
+
=> 0
|
88
|
+
|
89
|
+
allow_empty_search:
|
90
|
+
_true_ - match any occurrence
|
91
|
+
_false_ - match all ocurrences
|
92
|
+
Default is _false_.
|
93
|
+
|
94
|
+
search_in :brand, :name, { :tags => :name }, { :allow_empty_search => true }
|
95
|
+
|
96
|
+
Product.search("").size
|
97
|
+
=> 1
|
98
|
+
|
99
|
+
RoadMap
|
100
|
+
----
|
101
|
+
|
102
|
+
- Create a ignore list so the search can ignore some words
|
data/Rakefile
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
module MongoMapper
|
2
|
+
module Search
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
cattr_accessor :search_fields, :allow_empty_search, :stem_keywords, :match
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.included(base)
|
10
|
+
@classes ||= []
|
11
|
+
@classes << base
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.classes
|
15
|
+
@classes
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
|
20
|
+
def search_in(*args)
|
21
|
+
options = args.last.is_a?(Hash) && [:allow_empty_search, :stem_keywords].include?(args.last.keys.first) ? args.pop : {}
|
22
|
+
self.match = [:any, :all].include?(options[:match]) ? options[:match] : :any
|
23
|
+
self.allow_empty_search = [true, false].include?(options[:allow_empty_search]) ? options[:allow_empty_search] : false
|
24
|
+
self.stem_keywords = [true, false].include?(options[:stem_keywords]) ? options[:allow_empty_search] : false
|
25
|
+
self.search_fields = (self.search_fields || []).concat args
|
26
|
+
|
27
|
+
key :_keywords, Array
|
28
|
+
ensure_index :_keywords, :background => true
|
29
|
+
|
30
|
+
before_save :set_keywords
|
31
|
+
end
|
32
|
+
|
33
|
+
def search(query, options={})
|
34
|
+
return all if query.blank? && allow_empty_search
|
35
|
+
|
36
|
+
keywords = Util.normalize_keywords(query, stem_keywords)
|
37
|
+
|
38
|
+
regexed_keywords = []
|
39
|
+
|
40
|
+
keywords.each do |keyword|
|
41
|
+
regexed_keywords.concat([/#{keyword}/])
|
42
|
+
end
|
43
|
+
|
44
|
+
search_match = options[:match]||self.match
|
45
|
+
|
46
|
+
if search_match == :all
|
47
|
+
where(:_keywords => { "$all" => regexed_keywords })
|
48
|
+
elsif search_match == :any
|
49
|
+
where(:_keywords => regexed_keywords )
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Goes through all documents in the class that includes Mongoid::Search
|
54
|
+
# and indexes the keywords.
|
55
|
+
def index_keywords!
|
56
|
+
all.each { |d| d.index_keywords! }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module InstanceMethods #:nodoc:
|
61
|
+
# Indexes the document keywords
|
62
|
+
def index_keywords!
|
63
|
+
update_attribute(:_keywords, set_keywords)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def set_keywords
|
69
|
+
self._keywords = self.search_fields.map do |field|
|
70
|
+
Util.keywords(self, field, stem_keywords)
|
71
|
+
end.flatten.reject{|k| k.nil? || k.empty?}.uniq.sort
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Util
|
2
|
+
|
3
|
+
def self.keywords(klass, field, stem_keywords, ignore_list=[])
|
4
|
+
if field.is_a?(Hash)
|
5
|
+
field.keys.map do |key|
|
6
|
+
attribute = klass.send(key)
|
7
|
+
unless attribute.blank?
|
8
|
+
method = field[key]
|
9
|
+
if attribute.is_a?(Array)
|
10
|
+
if method.is_a?(Array)
|
11
|
+
method.map {|m| attribute.map { |a| Util.normalize_keywords a.send(m), stem_keywords, ignore_list } }
|
12
|
+
else
|
13
|
+
attribute.map(&method).map { |t| Util.normalize_keywords t, stem_keywords, ignore_list }
|
14
|
+
end
|
15
|
+
else
|
16
|
+
Util.normalize_keywords(attribute.send(method), stem_keywords, ignore_list)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
else
|
21
|
+
value = klass[field]
|
22
|
+
value = value.join(' ') if value.respond_to?(:join)
|
23
|
+
Util.normalize_keywords(value, stem_keywords, ignore_list) if value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.normalize_keywords(text, stem_keywords, ignore_list=[])
|
28
|
+
return [] if text.blank?
|
29
|
+
text = text.to_s.
|
30
|
+
mb_chars.
|
31
|
+
normalize(:kd).
|
32
|
+
to_s.
|
33
|
+
gsub(/[._:;'"`,?|+={}()!@#%^&*<>~\$\-\\\/\[\]]/, ' '). # strip punctuation
|
34
|
+
gsub(/[^[:alnum:]\s]/,''). # strip accents
|
35
|
+
downcase.
|
36
|
+
split(' ').
|
37
|
+
reject { |word| word.size < 2 }
|
38
|
+
text = text.reject { |word| ignore_list.include?(word) } unless ignore_list.blank?
|
39
|
+
text = text.map(&:stem) if stem_keywords
|
40
|
+
text
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Product
|
2
|
+
include MongoMapper::Document
|
3
|
+
include MongoMapper::Search
|
4
|
+
key :brand, String
|
5
|
+
key :name, String
|
6
|
+
key :attrs, Array
|
7
|
+
|
8
|
+
many :tags
|
9
|
+
many :subproducts
|
10
|
+
belongs_to :category
|
11
|
+
|
12
|
+
search_in :brand, :name, :outlet, :attrs, :tags => :name, :category => :name, :subproducts => [:brand, :name]
|
13
|
+
end
|
data/spec/models/tag.rb
ADDED
data/spec/search_spec.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
4
|
+
|
5
|
+
describe MongoMapper::Search do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
Product.stem_keywords = false
|
9
|
+
@product = Product.create :brand => "Apple",
|
10
|
+
:name => "iPhone",
|
11
|
+
:tags => ["Amazing", "Awesome", "Olé"].map { |tag| Tag.new(:name => tag) },
|
12
|
+
:category => Category.new(:name => "Mobile"),
|
13
|
+
:subproducts => [Subproduct.new(:brand => "Apple", :name => "Craddle")]
|
14
|
+
end
|
15
|
+
|
16
|
+
context "utf-8 characters" do
|
17
|
+
before(:each) {
|
18
|
+
Product.stem_keywords = false
|
19
|
+
@product = Product.create :brand => "Эльбрус",
|
20
|
+
:name => "Процессор",
|
21
|
+
:tags => ["Amazing", "Awesome", "Olé"].map { |tag| Tag.new(:name => tag) },
|
22
|
+
:category => Category.new(:name => "процессоры"),
|
23
|
+
:subproducts => []
|
24
|
+
}
|
25
|
+
|
26
|
+
it "should leave utf8 characters" do
|
27
|
+
@product._keywords.should == ["amazing", "awesome", "ole", "Процессор", "Эльбрус", "процессоры"]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when references are nil" do
|
32
|
+
context "when instance is being created" do
|
33
|
+
it "should not complain about method missing" do
|
34
|
+
lambda { Product.create! }.should_not raise_error
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
subject { Product.create :brand => "Apple", :name => "iPhone" }
|
39
|
+
|
40
|
+
its(:_keywords) { should == ["apple", "iphone"] }
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should set the _keywords field for array fields also" do
|
44
|
+
@product.attrs = ['lightweight', 'plastic', :red]
|
45
|
+
@product.save!
|
46
|
+
@product._keywords.should include 'lightweight', 'plastic', 'red'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should inherit _keywords field and build upon" do
|
50
|
+
variant = Variant.create :brand => "Apple",
|
51
|
+
:name => "iPhone",
|
52
|
+
:tags => ["Amazing", "Awesome", "Olé"].map { |tag| Tag.new(:name => tag) },
|
53
|
+
:category => Category.new(:name => "Mobile"),
|
54
|
+
:subproducts => [Subproduct.new(:brand => "Apple", :name => "Craddle")],
|
55
|
+
:color => :white
|
56
|
+
variant._keywords.should include 'white'
|
57
|
+
Variant.search("Apple white").to_a.should eq [variant]
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should set the _keywords field with stemmed words if stem is enabled" do
|
61
|
+
Product.stem_keywords = true
|
62
|
+
@product.save!
|
63
|
+
@product._keywords.should == ["amaz", "appl", "awesom", "craddl", "iphon", "mobil", "ol"]
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should incorporate numbers as keywords" do
|
67
|
+
@product = Product.create :brand => "Ford",
|
68
|
+
:name => "T 1908",
|
69
|
+
:tags => ["Amazing", "First", "Car"].map { |tag| Tag.new(:name => tag) },
|
70
|
+
:category => Category.new(:name => "Vehicle")
|
71
|
+
|
72
|
+
@product.save!
|
73
|
+
@product._keywords.should == ["1908","amazing", "car", "first", "ford", "vehicle"]
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
it "should return results in search" do
|
78
|
+
Product.search("apple").size.should == 1
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should return results in search for dynamic attribute" do
|
82
|
+
@product[:outlet] = "online shop"
|
83
|
+
@product.save!
|
84
|
+
Product.search("online").size.should == 1
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should return results in search even searching a accented word" do
|
88
|
+
Product.search("Ole").size.should == 1
|
89
|
+
Product.search("Olé").size.should == 1
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should return results in search even if the case doesn't match" do
|
93
|
+
Product.search("oLe").size.should == 1
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should return results in search with a partial word" do
|
97
|
+
Product.search("iph").size.should == 1
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should return results for any matching word with default search" do
|
101
|
+
Product.search("apple motorola").size.should == 1
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should not return results when all words do not match, if using :match => :all" do
|
105
|
+
Product.match = :all
|
106
|
+
Product.search("apple motorola").size.should == 0
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should return results for any matching word, using :match => :all, passing :match => :any to .search" do
|
110
|
+
Product.match = :all
|
111
|
+
Product.search("apple motorola", :match => :any).size.should == 1
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should not return results when all words do not match, passing :match => :all to .search" do
|
115
|
+
Product.search("apple motorola", :match => :all).size.should == 0
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should return no results when a blank search is made" do
|
119
|
+
Product.search("").size.should == 0
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should return results when a blank search is made when :allow_empty_search is true" do
|
123
|
+
Product.allow_empty_search = true
|
124
|
+
Product.search("").size.should == 1
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should search for embedded documents" do
|
128
|
+
Product.search("craddle").size.should == 1
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should work in a chainable fashion' do
|
132
|
+
@product.category.products.where(:brand => 'Apple').search('apple').size.should == 1
|
133
|
+
@product.category.products.where(:brand => 'Apple').search('troll').size.should == 0
|
134
|
+
@product.category.products.search('craddle').where(:brand => 'Apple').size.should == 1
|
135
|
+
@product.category.products.search('craddle').where(:brand => 'Dell').size.should == 0
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'should return the classes that include the search module' do
|
139
|
+
MongoMapper::Search.classes.should == [Product]
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should have a method to index keywords' do
|
143
|
+
@product.index_keywords!.should == true
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'should have a class method to index all documents keywords' do
|
147
|
+
Product.index_keywords!.should_not include(false)
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
require 'mongo_mapper'
|
7
|
+
require 'database_cleaner'
|
8
|
+
require 'fast_stemmer'
|
9
|
+
require 'yaml'
|
10
|
+
require 'mongomapper_search'
|
11
|
+
|
12
|
+
MongoMapper.connection = Mongo::Connection.new("localhost", 27017)
|
13
|
+
MongoMapper.database = "mongomapper_search_test"
|
14
|
+
|
15
|
+
Dir["#{File.dirname(__FILE__)}/models/*.rb"].each { |file| require file }
|
16
|
+
|
17
|
+
DatabaseCleaner.orm = :mongo_mapper
|
18
|
+
|
19
|
+
RSpec.configure do |config|
|
20
|
+
config.before(:all) do
|
21
|
+
DatabaseCleaner.strategy = :truncation
|
22
|
+
end
|
23
|
+
|
24
|
+
config.before(:each) do
|
25
|
+
DatabaseCleaner.start
|
26
|
+
end
|
27
|
+
|
28
|
+
config.after(:each) do
|
29
|
+
DatabaseCleaner.clean
|
30
|
+
end
|
31
|
+
end
|
data/spec/util_spec.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
3
|
+
|
4
|
+
describe Util do
|
5
|
+
it "should return an empty array if no text is passed" do
|
6
|
+
Util.normalize_keywords("", false, "").should == []
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return an array of keywords" do
|
10
|
+
Util.normalize_keywords("keyword", false, "").class.should == Array
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return an array of strings" do
|
14
|
+
Util.normalize_keywords("keyword", false, "").first.class.should == String
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should remove accents from the text passed" do
|
18
|
+
Util.normalize_keywords("café", false, "").should == ["cafe"]
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should downcase the text passed" do
|
22
|
+
Util.normalize_keywords("CaFé", false, "").should == ["cafe"]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should split whitespaces, hifens, dots, underlines, etc.." do
|
26
|
+
Util.normalize_keywords("CaFé-express.com delicious;come visit, and 'win' an \"iPad\"", false, "").should == ["cafe", "express", "com", "delicious", "come", "visit", "and", "win", "an", "ipad"]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should stem keywords" do
|
30
|
+
Util.normalize_keywords("A runner running and eating", true, "").should == ["runner", "run", "and", "eat"]
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should ignore keywords with less than two words" do
|
34
|
+
Util.normalize_keywords("A runner running", false, "").should_not include "a"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should not ignore numbers" do
|
38
|
+
Util.normalize_keywords("Ford T 1908", false, "").should include "1908"
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
metadata
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mongomapper_search
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mário Peixoto
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-18 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mongo_mapper
|
16
|
+
requirement: &70143029026220 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.9.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70143029026220
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: bson_ext
|
27
|
+
requirement: &70143029025740 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.2.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70143029025740
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: fast-stemmer
|
38
|
+
requirement: &70143029025260 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.0.0
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70143029025260
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: database_cleaner
|
49
|
+
requirement: &70143029024780 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.6.4
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70143029024780
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rake
|
60
|
+
requirement: &70143029024300 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 0.9.2
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70143029024300
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: &70143029023820 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '2.4'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70143029023820
|
80
|
+
description: Simple full text search for MongoMapper ODM
|
81
|
+
email:
|
82
|
+
- mario.peixoto@gmail.com
|
83
|
+
executables: []
|
84
|
+
extensions: []
|
85
|
+
extra_rdoc_files: []
|
86
|
+
files:
|
87
|
+
- lib/mongomapper_search/query.rb
|
88
|
+
- lib/mongomapper_search/search.rb
|
89
|
+
- lib/mongomapper_search/util.rb
|
90
|
+
- lib/mongomapper_search.rb
|
91
|
+
- LICENSE
|
92
|
+
- README.md
|
93
|
+
- Rakefile
|
94
|
+
- spec/models/category.rb
|
95
|
+
- spec/models/product.rb
|
96
|
+
- spec/models/subproduct.rb
|
97
|
+
- spec/models/tag.rb
|
98
|
+
- spec/models/variant.rb
|
99
|
+
- spec/search_spec.rb
|
100
|
+
- spec/spec_helper.rb
|
101
|
+
- spec/util_spec.rb
|
102
|
+
homepage: http://github.com/mariopeixoto/mongomapper_search
|
103
|
+
licenses: []
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ! '>='
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ! '>='
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: 1.3.6
|
120
|
+
requirements: []
|
121
|
+
rubyforge_project:
|
122
|
+
rubygems_version: 1.8.7
|
123
|
+
signing_key:
|
124
|
+
specification_version: 3
|
125
|
+
summary: Search implementation for MongoMapper ODM
|
126
|
+
test_files:
|
127
|
+
- spec/models/category.rb
|
128
|
+
- spec/models/product.rb
|
129
|
+
- spec/models/subproduct.rb
|
130
|
+
- spec/models/tag.rb
|
131
|
+
- spec/models/variant.rb
|
132
|
+
- spec/search_spec.rb
|
133
|
+
- spec/spec_helper.rb
|
134
|
+
- spec/util_spec.rb
|