picky 1.1.6 → 1.1.7
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/lib/picky/application.rb +1 -1
- data/lib/picky/index_api.rb +56 -25
- data/lib/picky/indexed/index.rb +2 -2
- data/lib/picky/query/allocation.rb +5 -5
- data/lib/picky/query/combinations.rb +3 -3
- data/lib/picky/query/weigher.rb +2 -2
- data/spec/lib/query/allocation_spec.rb +14 -14
- data/spec/lib/query/combinations_spec.rb +3 -3
- metadata +2 -2
data/lib/picky/application.rb
CHANGED
@@ -179,7 +179,7 @@ class Application
|
|
179
179
|
# * source: The source the data comes from. See Sources::Base. # TODO Sources (all).
|
180
180
|
#
|
181
181
|
# Options:
|
182
|
-
# *
|
182
|
+
# * result_identifier: # TODO Rename.
|
183
183
|
#
|
184
184
|
def index name, source, options = {}
|
185
185
|
IndexAPI.new name, source, options
|
data/lib/picky/index_api.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# This class defines the indexing and index API that is exposed to the user
|
2
2
|
# as the #index method inside the Application class.
|
3
3
|
#
|
4
|
-
# It provides a single front for both indexing and index options.
|
4
|
+
# It provides a single front for both indexing and index options. We suggest to always use the index API.
|
5
5
|
#
|
6
6
|
# Note: An Index holds both an *Indexed*::*Index* and an *Indexing*::*Type*.
|
7
7
|
#
|
@@ -11,12 +11,13 @@ class IndexAPI
|
|
11
11
|
|
12
12
|
# Create a new index with a given source.
|
13
13
|
#
|
14
|
-
# Parameters
|
14
|
+
# === Parameters
|
15
15
|
# * name: A name that will be used for the index directory and in the Picky front end.
|
16
16
|
# * source: Where the data comes from, e.g. Sources::CSV.new(...)
|
17
17
|
#
|
18
|
-
# Options
|
19
|
-
# *
|
18
|
+
# === Options
|
19
|
+
# * result_identifier: Use if you'd like a different identifier/name in the results than the name of the index.
|
20
|
+
# * after_indexing: As of this writing only used in the db source. Executes the given after_indexing as SQL after the indexing process.
|
20
21
|
#
|
21
22
|
def initialize name, source, options = {}
|
22
23
|
@name = name
|
@@ -30,10 +31,10 @@ class IndexAPI
|
|
30
31
|
|
31
32
|
# Defines a searchable category on the index.
|
32
33
|
#
|
33
|
-
# Parameters
|
34
|
-
# category_name: This identifier is used in the front end, but also to categorize query text. For example, “title:hobbit” will narrow the hobbit query on categories with the identifier :title.
|
34
|
+
# === Parameters
|
35
|
+
# * category_name: This identifier is used in the front end, but also to categorize query text. For example, “title:hobbit” will narrow the hobbit query on categories with the identifier :title.
|
35
36
|
#
|
36
|
-
# Options
|
37
|
+
# === Options
|
37
38
|
# * partial: Partial::None.new or Partial::Substring.new(from: starting_char, to: ending_char). Default is Partial::Substring.new(from: -3, to: -1).
|
38
39
|
# * similarity: Similarity::None.new or Similarity::Phonetic.new(similar_words_searched). Default is Similarity::None.new.
|
39
40
|
# * qualifiers: An array of qualifiers with which you can define which category you’d like to search, for example “title:hobbit” will search for hobbit in just title categories. Example: qualifiers: [:t, :titre, :title] (use it for example with multiple languages). Default is the name of the category.
|
@@ -53,9 +54,9 @@ class IndexAPI
|
|
53
54
|
end
|
54
55
|
alias category define_category
|
55
56
|
|
56
|
-
# HIGHLY EXPERIMENTAL
|
57
|
+
# HIGHLY EXPERIMENTAL Try if you feel "beta" ;)
|
57
58
|
#
|
58
|
-
# Make this category range searchable.
|
59
|
+
# Make this category range searchable with a fixed range. If you need other ranges, define another category with a different range value.
|
59
60
|
#
|
60
61
|
# Example:
|
61
62
|
# You have data values inside 1..100, and you want to have Picky return
|
@@ -63,33 +64,61 @@ class IndexAPI
|
|
63
64
|
# 45, 46, or 47.2, 48.9, in a range of 2 around 47, so (45..49).
|
64
65
|
#
|
65
66
|
# Then you use:
|
66
|
-
# my_index.
|
67
|
+
# my_index.define_ranged_category :values_inside_1_100, 2
|
67
68
|
#
|
68
69
|
# Optionally, you give it a precision value to reduce the error margin
|
69
70
|
# around 47 (Picky is a bit liberal).
|
70
|
-
# my_index.
|
71
|
+
# my_index.define_ranged_category :values_inside_1_100, 2, precision: 5
|
71
72
|
#
|
72
73
|
# This will force Picky to maximally be wrong 5% of the given range value
|
73
|
-
# (5% of 2 = 0.1).
|
74
|
+
# (5% of 2 = 0.1) instead of the default 20% (20% of 2 = 0.4).
|
74
75
|
#
|
75
|
-
# We suggest not to use more than 5 as a higher precision is more performance intensive.
|
76
|
+
# We suggest not to use much more than 5 as a higher precision is more performance intensive for less and less precision gain.
|
76
77
|
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
78
|
+
# == Protip 1
|
79
|
+
#
|
80
|
+
# Create two ranged categories to make an area search:
|
81
|
+
# index.define_ranged_category :x, 1
|
82
|
+
# index.define_ranged_category :y, 1
|
83
|
+
#
|
84
|
+
# Search for it using for example:
|
85
|
+
# x:133, y:120
|
86
|
+
#
|
87
|
+
# This will search this square area (* = 133, 120: The "search" point entered):
|
88
|
+
#
|
89
|
+
# 132 134
|
90
|
+
# | |
|
91
|
+
# --|---------|-- 121
|
92
|
+
# | |
|
93
|
+
# | * |
|
94
|
+
# | |
|
95
|
+
# --|---------|-- 119
|
96
|
+
# | |
|
97
|
+
#
|
98
|
+
# Note: The area does not need to be square, but can be rectangular.
|
99
|
+
#
|
100
|
+
# == Protip 2
|
101
|
+
#
|
102
|
+
# Create three ranged categories to make a volume search.
|
103
|
+
#
|
104
|
+
# Or go crazy and use 4 ranged categories for a space/time search! ;)
|
105
|
+
#
|
106
|
+
# === Parameters
|
107
|
+
# * category_name: The category_name as used in #define_category.
|
108
|
+
# * range: The range (in the units of your data values) around the query point where we search for results.
|
80
109
|
#
|
81
110
|
# -----|<- range ->*------------|-----
|
82
111
|
#
|
83
|
-
# Options
|
84
|
-
# * precision
|
85
|
-
# *
|
112
|
+
# === Options
|
113
|
+
# * precision: Default is 1 (20% error margin, very fast), up to 5 (5% error margin, slower) makes sense.
|
114
|
+
# * ... all options of #define_category.
|
86
115
|
#
|
87
|
-
def
|
116
|
+
def define_ranged_category category_name, range, options = {}
|
88
117
|
precision = options[:precision]
|
89
118
|
|
90
119
|
options = { partial: Partial::None.new }.merge options
|
91
120
|
|
92
|
-
define_category
|
121
|
+
define_category category_name, options do |indexing, indexed|
|
93
122
|
indexing.source = Sources::Wrappers::Location.new indexing, grid: range, precision: precision
|
94
123
|
indexing.tokenizer = Tokenizers::Index.new
|
95
124
|
|
@@ -98,11 +127,11 @@ class IndexAPI
|
|
98
127
|
indexed.partial = exact_bundle # A partial token also uses the exact index.
|
99
128
|
end
|
100
129
|
end
|
101
|
-
alias
|
130
|
+
alias ranged_category define_ranged_category
|
102
131
|
|
103
132
|
# HIGHLY EXPERIMENTAL Not correctly working yet. Try it if you feel "beta".
|
104
133
|
#
|
105
|
-
# Also a range search see #
|
134
|
+
# Also a range search see #define_ranged_category, but on the earth's surface.
|
106
135
|
#
|
107
136
|
# Parameters:
|
108
137
|
# * name: The name as used in #define_category.
|
@@ -128,7 +157,9 @@ class IndexAPI
|
|
128
157
|
# * precision: Default 1 (20% error margin, very fast), up to 5 (5% error margin, slower) makes sense.
|
129
158
|
# * from: The data category to take the data for this category from.
|
130
159
|
#
|
131
|
-
|
160
|
+
# TODO Redo. Probably extract into define_latitude_category, define_longitude_category.
|
161
|
+
#
|
162
|
+
def define_map_location name, radius, options = {} # :nodoc:
|
132
163
|
# The radius is given as if all the locations were on the equator.
|
133
164
|
#
|
134
165
|
# TODO Need to recalculate since not many locations are on the equator ;) This is just a prototype.
|
@@ -138,7 +169,7 @@ class IndexAPI
|
|
138
169
|
# A degree on the equator is equal to ~111,319.9 meters.
|
139
170
|
# So a km on the equator is equal to 0.00898312 degrees.
|
140
171
|
#
|
141
|
-
|
172
|
+
define_ranged_category name, radius * 0.00898312, options
|
142
173
|
end
|
143
174
|
alias map_location define_map_location
|
144
175
|
end
|
data/lib/picky/indexed/index.rb
CHANGED
@@ -4,7 +4,7 @@ module Indexed
|
|
4
4
|
#
|
5
5
|
class Index
|
6
6
|
|
7
|
-
attr_reader :name, :
|
7
|
+
attr_reader :name, :result_identifier, :combinator, :categories
|
8
8
|
|
9
9
|
delegate :load_from_cache,
|
10
10
|
:to => :categories
|
@@ -12,7 +12,7 @@ module Indexed
|
|
12
12
|
def initialize name, options = {}
|
13
13
|
@name = name
|
14
14
|
|
15
|
-
@
|
15
|
+
@result_identifier = options[:result_identifier] || name
|
16
16
|
ignore_unassigned_tokens = options[:ignore_unassigned_tokens] || false # TODO Move to query, somehow.
|
17
17
|
|
18
18
|
@categories = Categories.new ignore_unassigned_tokens: ignore_unassigned_tokens
|
@@ -4,13 +4,13 @@ module Query
|
|
4
4
|
#
|
5
5
|
class Allocation # :nodoc:all
|
6
6
|
|
7
|
-
attr_reader :count, :ids, :score, :combinations, :
|
7
|
+
attr_reader :count, :ids, :score, :combinations, :result_identifier
|
8
8
|
|
9
9
|
#
|
10
10
|
#
|
11
|
-
def initialize combinations,
|
12
|
-
@combinations
|
13
|
-
@
|
11
|
+
def initialize combinations, result_identifier
|
12
|
+
@combinations = combinations
|
13
|
+
@result_identifier = result_identifier
|
14
14
|
end
|
15
15
|
|
16
16
|
def hash
|
@@ -61,7 +61,7 @@ module Query
|
|
61
61
|
# Transform the allocation into result form.
|
62
62
|
#
|
63
63
|
def to_result
|
64
|
-
[self.
|
64
|
+
[self.result_identifier, self.score, self.count, @combinations.to_result, self.ids] if self.count > 0
|
65
65
|
end
|
66
66
|
|
67
67
|
# Json representation of this allocation.
|
@@ -62,10 +62,10 @@ module Query
|
|
62
62
|
Performant::Array.memory_efficient_intersect id_arrays
|
63
63
|
end
|
64
64
|
|
65
|
-
# Wrap the combinations into an allocation with the
|
65
|
+
# Wrap the combinations into an allocation with the result_identifier.
|
66
66
|
#
|
67
|
-
def pack_into_allocation
|
68
|
-
Allocation.new self,
|
67
|
+
def pack_into_allocation result_identifier
|
68
|
+
Allocation.new self, result_identifier
|
69
69
|
end
|
70
70
|
|
71
71
|
# Filters the tokens and identifiers such that only identifiers
|
data/lib/picky/query/weigher.rb
CHANGED
@@ -53,7 +53,7 @@ module Query
|
|
53
53
|
|
54
54
|
# Wrap into a real combination.
|
55
55
|
#
|
56
|
-
# expanded_combinations.map! { |expanded_combination| Combinations.new(expanded_combination).pack_into_allocation(index.
|
56
|
+
# expanded_combinations.map! { |expanded_combination| Combinations.new(expanded_combination).pack_into_allocation(index.result_identifier) }
|
57
57
|
|
58
58
|
# Add the possible allocations to the ones we already have.
|
59
59
|
#
|
@@ -63,7 +63,7 @@ module Query
|
|
63
63
|
# Add the wrapped possible allocations to the ones we already have.
|
64
64
|
#
|
65
65
|
previous_allocations + expanded_combinations.map! do |expanded_combination|
|
66
|
-
Combinations.new(expanded_combination).pack_into_allocation(index.
|
66
|
+
Combinations.new(expanded_combination).pack_into_allocation(index.result_identifier) # TODO Do not extract result_identifier. Remove pack_into_allocation.
|
67
67
|
end
|
68
68
|
end)
|
69
69
|
end
|
@@ -4,7 +4,7 @@ describe Query::Allocation do
|
|
4
4
|
|
5
5
|
before(:each) do
|
6
6
|
@combinations = stub :combinations
|
7
|
-
@allocation = Query::Allocation.new @combinations, :
|
7
|
+
@allocation = Query::Allocation.new @combinations, :some_result_identifier
|
8
8
|
end
|
9
9
|
|
10
10
|
describe "eql?" do
|
@@ -34,7 +34,7 @@ describe Query::Allocation do
|
|
34
34
|
@allocation.stub! :ids => :ids
|
35
35
|
end
|
36
36
|
it "represents correctly" do
|
37
|
-
@allocation.to_s.should == "Allocation:
|
37
|
+
@allocation.to_s.should == "Allocation: some_result_identifier, score, 10, combinations_result, ids"
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -104,34 +104,34 @@ describe Query::Allocation do
|
|
104
104
|
describe 'to_result' do
|
105
105
|
context 'with few combinations' do
|
106
106
|
before(:each) do
|
107
|
-
@allocation = Query::Allocation.new stub(:combinations, :ids => [1,2,3], :to_result => [:some_result]), :
|
107
|
+
@allocation = Query::Allocation.new stub(:combinations, :ids => [1,2,3], :to_result => [:some_result]), :some_result_identifier
|
108
108
|
@allocation.instance_variable_set :@score, :some_score
|
109
109
|
end
|
110
110
|
context 'with ids' do
|
111
111
|
it 'should output an array of information' do
|
112
112
|
@allocation.process! 20, 0
|
113
113
|
|
114
|
-
@allocation.to_result.should == [:
|
114
|
+
@allocation.to_result.should == [:some_result_identifier, :some_score, 3, [:some_result], [1, 2, 3]]
|
115
115
|
end
|
116
116
|
end
|
117
117
|
end
|
118
118
|
context 'with results' do
|
119
119
|
before(:each) do
|
120
120
|
combinations = stub :combinations, :ids => [1,2,3], :to_result => [:some_result1, :some_result2]
|
121
|
-
@allocation = Query::Allocation.new combinations, :
|
121
|
+
@allocation = Query::Allocation.new combinations, :some_result_identifier
|
122
122
|
@allocation.instance_variable_set :@score, :some_score
|
123
123
|
end
|
124
124
|
context 'with ids' do
|
125
125
|
it 'should output an array of information' do
|
126
126
|
@allocation.process! 20, 0
|
127
127
|
|
128
|
-
@allocation.to_result.should == [:
|
128
|
+
@allocation.to_result.should == [:some_result_identifier, :some_score, 3, [:some_result1, :some_result2], [1, 2, 3]]
|
129
129
|
end
|
130
130
|
end
|
131
131
|
end
|
132
132
|
context 'without results' do
|
133
133
|
before(:each) do
|
134
|
-
@allocation = Query::Allocation.new stub(:combinations, :ids => [], :to_result => []), :
|
134
|
+
@allocation = Query::Allocation.new stub(:combinations, :ids => [], :to_result => []), :some_result_identifier
|
135
135
|
@allocation.instance_variable_set :@score, :some_score
|
136
136
|
end
|
137
137
|
it 'should return nil' do
|
@@ -144,13 +144,13 @@ describe Query::Allocation do
|
|
144
144
|
|
145
145
|
describe 'to_json' do
|
146
146
|
before(:each) do
|
147
|
-
@allocation = Query::Allocation.new stub(:combination, :ids => [1,2,3,4,5,6,7], :to_result => [:some_result1, :some_result2]), :
|
147
|
+
@allocation = Query::Allocation.new stub(:combination, :ids => [1,2,3,4,5,6,7], :to_result => [:some_result1, :some_result2]), :some_result_identifier
|
148
148
|
@allocation.instance_variable_set :@score, :some_score
|
149
149
|
end
|
150
150
|
it 'should output the correct json string' do
|
151
151
|
@allocation.process! 20, 0
|
152
152
|
|
153
|
-
@allocation.to_json.should == '["
|
153
|
+
@allocation.to_json.should == '["some_result_identifier","some_score",7,["some_result1","some_result2"],[1,2,3,4,5,6,7]]'
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|
@@ -164,9 +164,9 @@ describe Query::Allocation do
|
|
164
164
|
|
165
165
|
describe "<=>" do
|
166
166
|
it "should sort higher first" do
|
167
|
-
first = Query::Allocation.new [], :
|
167
|
+
first = Query::Allocation.new [], :some_result_identifier
|
168
168
|
first.instance_variable_set :@score, 20
|
169
|
-
second = Query::Allocation.new [], :
|
169
|
+
second = Query::Allocation.new [], :some_result_identifier
|
170
170
|
second.instance_variable_set :@score, 10
|
171
171
|
|
172
172
|
first.<=>(second).should == -1
|
@@ -175,11 +175,11 @@ describe Query::Allocation do
|
|
175
175
|
|
176
176
|
describe "sort!" do
|
177
177
|
it "should sort correctly" do
|
178
|
-
first = Query::Allocation.new :whatever, :
|
178
|
+
first = Query::Allocation.new :whatever, :some_result_identifier
|
179
179
|
first.instance_variable_set :@score, 20
|
180
|
-
second = Query::Allocation.new :whatever, :
|
180
|
+
second = Query::Allocation.new :whatever, :some_result_identifier
|
181
181
|
second.instance_variable_set :@score, 10
|
182
|
-
third = Query::Allocation.new :whatever, :
|
182
|
+
third = Query::Allocation.new :whatever, :some_result_identifier
|
183
183
|
third.instance_variable_set :@score, 5
|
184
184
|
|
185
185
|
allocations = [second, third, first]
|
@@ -12,10 +12,10 @@ describe 'Query::Combinations' do
|
|
12
12
|
|
13
13
|
describe "pack_into_allocation" do
|
14
14
|
it "return an Allocation" do
|
15
|
-
@combinations.pack_into_allocation(:
|
15
|
+
@combinations.pack_into_allocation(:some_result_identifier).should be_kind_of(Query::Allocation)
|
16
16
|
end
|
17
|
-
it "returns an Allocation with specific
|
18
|
-
@combinations.pack_into_allocation(:
|
17
|
+
it "returns an Allocation with specific result_identifier" do
|
18
|
+
@combinations.pack_into_allocation(:some_result_identifier).result_identifier.should == :some_result_identifier
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|