lunar 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +3 -1
- data/VERSION +1 -1
- data/lib/lunar.rb +34 -29
- data/lib/lunar/connection.rb +12 -1
- data/lib/lunar/fuzzy_word.rb +9 -1
- data/lib/lunar/index.rb +2 -2
- data/lib/lunar/result_set.rb +5 -7
- data/lib/lunar/stopwords.rb +2 -0
- data/lunar.gemspec +1 -1
- metadata +2 -2
data/README.markdown
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
Lunar: full text searching on top of Redis
|
2
2
|
==========================================
|
3
3
|
|
4
|
+
Read the documentation at http://sinefunc.github.com/lunar/doc
|
5
|
+
|
4
6
|
But why?
|
5
7
|
--------
|
6
8
|
We have been using Redis as our datastore exclusively for a lot of projects.
|
@@ -113,4 +115,4 @@ Note on Patches/Pull Requests
|
|
113
115
|
|
114
116
|
### Copyright
|
115
117
|
|
116
|
-
Copyright (c) 2010 Cyril David. See LICENSE for details.
|
118
|
+
Copyright (c) 2010 Cyril David. See LICENSE for details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.1
|
data/lib/lunar.rb
CHANGED
@@ -4,7 +4,7 @@ require 'nest'
|
|
4
4
|
require 'text'
|
5
5
|
|
6
6
|
module Lunar
|
7
|
-
VERSION = '0.5.
|
7
|
+
VERSION = '0.5.1'
|
8
8
|
|
9
9
|
autoload :Connection, "lunar/connection"
|
10
10
|
autoload :LunarNest, "lunar/lunar_nest"
|
@@ -23,7 +23,7 @@ module Lunar
|
|
23
23
|
# Index any document using a namespace. The namespace can
|
24
24
|
# be a class, or a plain Symbol/String.
|
25
25
|
#
|
26
|
-
# @example
|
26
|
+
# @example
|
27
27
|
#
|
28
28
|
# Lunar.index Gadget do |i|
|
29
29
|
# i.text :name, 'iphone 3gs'
|
@@ -54,7 +54,7 @@ module Lunar
|
|
54
54
|
|
55
55
|
# Search for a document, scoped under a namespace.
|
56
56
|
#
|
57
|
-
# @example
|
57
|
+
# @example
|
58
58
|
#
|
59
59
|
# Lunar.search Gadget, :q => "apple"
|
60
60
|
# # returns all gadgets with `text` apple.
|
@@ -82,32 +82,10 @@ module Lunar
|
|
82
82
|
#
|
83
83
|
# @return Lunar::ResultSet an Enumerable object.
|
84
84
|
def self.search(namespace, options, finder = lambda { |id| namespace[id] })
|
85
|
-
|
85
|
+
sets = find_and_combine_sorted_sets_for(namespace, options)
|
86
|
+
key = try_intersection_of_sorted_sets(namespace, sets)
|
86
87
|
|
87
|
-
|
88
|
-
options.map do |key, value|
|
89
|
-
if value.is_a?(Range)
|
90
|
-
RangeMatches.new(nest[namespace], key, value).distkey
|
91
|
-
elsif key == :fuzzy
|
92
|
-
value.map do |fuzzy_key, fuzzy_value|
|
93
|
-
FuzzyMatches.new(nest[namespace], fuzzy_key, fuzzy_value).distkey
|
94
|
-
end
|
95
|
-
else
|
96
|
-
KeywordMatches.new(nest[namespace], key, value).distkey
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
sets = sets.flatten
|
101
|
-
|
102
|
-
key =
|
103
|
-
if sets.size == 1
|
104
|
-
sets.first
|
105
|
-
else
|
106
|
-
ns[options.hash].zinterstore sets
|
107
|
-
ns[options.hash]
|
108
|
-
end
|
109
|
-
|
110
|
-
ResultSet.new(key, ns, finder)
|
88
|
+
ResultSet.new(key, nest[namespace], finder)
|
111
89
|
end
|
112
90
|
|
113
91
|
# @private internally used for determining the metaphone of a word.
|
@@ -124,4 +102,31 @@ module Lunar
|
|
124
102
|
def self.nest
|
125
103
|
LunarNest.new(:Lunar, redis)
|
126
104
|
end
|
127
|
-
|
105
|
+
|
106
|
+
private
|
107
|
+
def self.find_and_combine_sorted_sets_for(namespace, options)
|
108
|
+
options.inject([]) do |sets, (key, value)|
|
109
|
+
if value.is_a?(Range)
|
110
|
+
sets << RangeMatches.new(nest[namespace], key, value).distkey
|
111
|
+
elsif key == :fuzzy
|
112
|
+
fuzzy_matches = value.map { |fuzzy_key, fuzzy_value|
|
113
|
+
FuzzyMatches.new(nest[namespace], fuzzy_key, fuzzy_value).distkey
|
114
|
+
}
|
115
|
+
sets.push(*fuzzy_matches)
|
116
|
+
else
|
117
|
+
sets << KeywordMatches.new(nest[namespace], key, value).distkey
|
118
|
+
end
|
119
|
+
|
120
|
+
sets
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.try_intersection_of_sorted_sets(namespace, sets)
|
125
|
+
if sets.size == 1
|
126
|
+
sets.first
|
127
|
+
else
|
128
|
+
nest[namespace][options.hash].zinterstore sets
|
129
|
+
nest[namespace][options.hash]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/lib/lunar/connection.rb
CHANGED
@@ -1,4 +1,15 @@
|
|
1
1
|
module Lunar
|
2
|
+
# This is actually taken from Ohm (http://ohm.keyvalue.org). The Lunar module
|
3
|
+
# extends this to make the API easier to use.
|
4
|
+
#
|
5
|
+
# Lunar.connect(:host => "127.0.0.1", :port => "6380")
|
6
|
+
# Lunar.redis
|
7
|
+
# # basically returns Redis.new(:host => "127.0.0.1", :port => "6380")
|
8
|
+
#
|
9
|
+
# # If you don't provide any connection, it assumes you are referring
|
10
|
+
# # to the default redis host / port (127.0.0.1 on port 6379)
|
11
|
+
# Lunar.redis
|
12
|
+
#
|
2
13
|
module Connection
|
3
14
|
# Connect to a redis database.
|
4
15
|
#
|
@@ -48,4 +59,4 @@ module Lunar
|
|
48
59
|
@options || []
|
49
60
|
end
|
50
61
|
end
|
51
|
-
end
|
62
|
+
end
|
data/lib/lunar/fuzzy_word.rb
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
module Lunar
|
2
|
+
# @private A helper for producing all the characters of a word.
|
3
|
+
#
|
4
|
+
# @example
|
5
|
+
#
|
6
|
+
# expected = %w(a ab abr abra abrah abraha abraham)
|
7
|
+
# FuzzyWord.new("Abraham").partials == expected
|
8
|
+
# # => true
|
9
|
+
#
|
2
10
|
class FuzzyWord < String
|
3
11
|
def partials
|
4
12
|
(1..length).map { |i| self[0, i].downcase }
|
5
13
|
end
|
6
14
|
end
|
7
|
-
end
|
15
|
+
end
|
data/lib/lunar/index.rb
CHANGED
data/lib/lunar/result_set.rb
CHANGED
@@ -2,8 +2,6 @@ module Lunar
|
|
2
2
|
# This wraps a Lunar search result set. You can do all the
|
3
3
|
# expected operations with an Enumerable.
|
4
4
|
#
|
5
|
-
# @example:
|
6
|
-
#
|
7
5
|
# results = Lunar.search(Gadget, :q => "Apple Macbook Pro")
|
8
6
|
# results.class == Lunar::ResultSet
|
9
7
|
# # => true
|
@@ -11,8 +9,8 @@ module Lunar
|
|
11
9
|
# results.kind_of?(Enumerable)
|
12
10
|
# # => true
|
13
11
|
#
|
14
|
-
#
|
15
|
-
# the Redis SORT command.
|
12
|
+
# {Lunar::ResultSet#sort} and {Lunar::ResultSet#sort_by} commands are
|
13
|
+
# available and directly calls the Redis SORT command.
|
16
14
|
#
|
17
15
|
# results = Lunar.search(Gadget, :q => "Apple Macbook Pro")
|
18
16
|
# results.sort(:by => :name, :order => "ALPHA")
|
@@ -40,7 +38,7 @@ module Lunar
|
|
40
38
|
|
41
39
|
# Provides syntatic sugar for `sort`.
|
42
40
|
#
|
43
|
-
# @example
|
41
|
+
# @example
|
44
42
|
#
|
45
43
|
# results = Lunar.search(Gadget, :q => "apple")
|
46
44
|
# results.sort(:by => :votes)
|
@@ -60,7 +58,7 @@ module Lunar
|
|
60
58
|
# Gives the ability to sort the search results via a `sortable` field
|
61
59
|
# in your index.
|
62
60
|
#
|
63
|
-
# @example
|
61
|
+
# @example
|
64
62
|
#
|
65
63
|
# Lunar.index Gadget do |i|
|
66
64
|
# i.id 1001
|
@@ -97,4 +95,4 @@ module Lunar
|
|
97
95
|
ids.map(&@finder)
|
98
96
|
end
|
99
97
|
end
|
100
|
-
end
|
98
|
+
end
|
data/lib/lunar/stopwords.rb
CHANGED
data/lunar.gemspec
CHANGED