picky 2.7.0 → 3.0.0.pre1
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/adapters/rack/base.rb +20 -16
- data/lib/picky/adapters/rack/live_parameters.rb +28 -24
- data/lib/picky/adapters/rack/search.rb +67 -0
- data/lib/picky/adapters/rack.rb +27 -23
- data/lib/picky/application.rb +246 -236
- data/lib/picky/backend/base.rb +115 -119
- data/lib/picky/backend/file/basic.rb +102 -98
- data/lib/picky/backend/file/json.rb +27 -23
- data/lib/picky/backend/file/marshal.rb +32 -28
- data/lib/picky/backend/file/text.rb +45 -41
- data/lib/picky/backend/files.rb +19 -15
- data/lib/picky/backend/redis/basic.rb +76 -72
- data/lib/picky/backend/redis/list_hash.rb +40 -36
- data/lib/picky/backend/redis/string_hash.rb +30 -26
- data/lib/picky/backend/redis.rb +32 -28
- data/lib/picky/bundle.rb +82 -57
- data/lib/{bundling.rb → picky/bundling.rb} +0 -0
- data/lib/picky/calculations/location.rb +51 -47
- data/lib/picky/categories.rb +60 -56
- data/lib/picky/categories_indexed.rb +73 -82
- data/lib/picky/categories_indexing.rb +12 -8
- data/lib/picky/category.rb +109 -120
- data/lib/picky/category_indexed.rb +39 -41
- data/lib/picky/category_indexing.rb +123 -125
- data/lib/picky/character_substituters/west_european.rb +32 -26
- data/lib/{constants.rb → picky/constants.rb} +0 -0
- data/lib/picky/cores.rb +96 -92
- data/lib/{deployment.rb → picky/deployment.rb} +0 -0
- data/lib/picky/frontend_adapters/rack.rb +133 -118
- data/lib/picky/generators/aliases.rb +5 -3
- data/lib/picky/generators/base.rb +11 -7
- data/lib/picky/generators/partial/default.rb +7 -3
- data/lib/picky/generators/partial/none.rb +24 -20
- data/lib/picky/generators/partial/strategy.rb +20 -16
- data/lib/picky/generators/partial/substring.rb +94 -90
- data/lib/picky/generators/partial_generator.rb +11 -7
- data/lib/picky/generators/similarity/default.rb +9 -5
- data/lib/picky/generators/similarity/double_metaphone.rb +20 -16
- data/lib/picky/generators/similarity/metaphone.rb +20 -16
- data/lib/picky/generators/similarity/none.rb +23 -19
- data/lib/picky/generators/similarity/phonetic.rb +49 -45
- data/lib/picky/generators/similarity/soundex.rb +20 -16
- data/lib/picky/generators/similarity/strategy.rb +10 -6
- data/lib/picky/generators/similarity_generator.rb +11 -7
- data/lib/picky/generators/strategy.rb +14 -10
- data/lib/picky/generators/weights/default.rb +9 -5
- data/lib/picky/generators/weights/logarithmic.rb +30 -26
- data/lib/picky/generators/weights/strategy.rb +10 -6
- data/lib/picky/generators/weights_generator.rb +11 -7
- data/lib/picky/helpers/measuring.rb +20 -16
- data/lib/picky/indexed/bundle/base.rb +39 -37
- data/lib/picky/indexed/bundle/memory.rb +68 -64
- data/lib/picky/indexed/bundle/redis.rb +73 -69
- data/lib/picky/indexed/wrappers/bundle/calculation.rb +26 -22
- data/lib/picky/indexed/wrappers/bundle/location.rb +30 -26
- data/lib/picky/indexed/wrappers/bundle/wrapper.rb +36 -32
- data/lib/picky/indexed/wrappers/category/location.rb +17 -13
- data/lib/picky/indexed/wrappers/exact_first.rb +46 -42
- data/lib/picky/indexers/base.rb +26 -22
- data/lib/picky/indexers/parallel.rb +62 -58
- data/lib/picky/indexers/serial.rb +41 -37
- data/lib/picky/indexes/index.rb +400 -0
- data/lib/picky/indexes/index_indexed.rb +24 -0
- data/lib/picky/indexes/index_indexing.rb +138 -0
- data/lib/picky/indexes/memory.rb +20 -0
- data/lib/picky/indexes/redis.rb +20 -0
- data/lib/picky/indexes.rb +68 -61
- data/lib/picky/indexes_indexed.rb +16 -12
- data/lib/picky/indexes_indexing.rb +41 -37
- data/lib/picky/indexing/bundle/base.rb +216 -205
- data/lib/picky/indexing/bundle/memory.rb +16 -11
- data/lib/picky/indexing/bundle/redis.rb +14 -12
- data/lib/picky/indexing/wrappers/category/location.rb +17 -13
- data/lib/picky/interfaces/live_parameters.rb +159 -154
- data/lib/picky/loader.rb +267 -304
- data/lib/picky/loggers/search.rb +20 -13
- data/lib/picky/no_source_specified_exception.rb +7 -3
- data/lib/picky/performant.rb +6 -2
- data/lib/picky/query/allocation.rb +71 -67
- data/lib/picky/query/allocations.rb +99 -94
- data/lib/picky/query/combination.rb +70 -66
- data/lib/picky/query/combinations/base.rb +56 -52
- data/lib/picky/query/combinations/memory.rb +36 -32
- data/lib/picky/query/combinations/redis.rb +66 -62
- data/lib/picky/query/indexes.rb +175 -160
- data/lib/picky/query/qualifier_category_mapper.rb +43 -0
- data/lib/picky/query/token.rb +165 -172
- data/lib/picky/query/tokens.rb +86 -82
- data/lib/picky/query/weights.rb +44 -48
- data/lib/picky/query.rb +5 -1
- data/lib/picky/rack/harakiri.rb +51 -47
- data/lib/picky/results.rb +81 -77
- data/lib/picky/search.rb +169 -158
- data/lib/picky/sinatra.rb +34 -0
- data/lib/picky/sources/base.rb +73 -70
- data/lib/picky/sources/couch.rb +61 -57
- data/lib/picky/sources/csv.rb +68 -64
- data/lib/picky/sources/db.rb +139 -135
- data/lib/picky/sources/delicious.rb +52 -48
- data/lib/picky/sources/mongo.rb +68 -63
- data/lib/picky/sources/wrappers/base.rb +20 -16
- data/lib/picky/sources/wrappers/location.rb +37 -33
- data/lib/picky/statistics.rb +46 -43
- data/lib/picky/tasks.rb +3 -0
- data/lib/picky/tokenizers/base.rb +192 -187
- data/lib/picky/tokenizers/index.rb +25 -21
- data/lib/picky/tokenizers/location.rb +33 -29
- data/lib/picky/tokenizers/query.rb +49 -43
- data/lib/picky.rb +21 -13
- data/lib/tasks/application.rake +1 -1
- data/lib/tasks/index.rake +3 -3
- data/lib/tasks/routes.rake +1 -1
- data/lib/tasks/server.rake +1 -1
- data/spec/lib/adapters/rack/base_spec.rb +1 -1
- data/spec/lib/adapters/rack/live_parameters_spec.rb +1 -1
- data/spec/lib/adapters/rack/query_spec.rb +1 -1
- data/spec/lib/application_spec.rb +39 -32
- data/spec/lib/backend/file/basic_spec.rb +2 -2
- data/spec/lib/backend/file/json_spec.rb +2 -2
- data/spec/lib/backend/file/marshal_spec.rb +2 -2
- data/spec/lib/backend/file/text_spec.rb +1 -1
- data/spec/lib/backend/files_spec.rb +14 -24
- data/spec/lib/backend/redis/basic_spec.rb +2 -2
- data/spec/lib/backend/redis/list_hash_spec.rb +3 -3
- data/spec/lib/backend/redis/string_hash_spec.rb +3 -3
- data/spec/lib/backend/redis_spec.rb +20 -13
- data/spec/lib/calculations/location_spec.rb +1 -1
- data/spec/lib/categories_indexed_spec.rb +16 -34
- data/spec/lib/category_indexed_spec.rb +9 -27
- data/spec/lib/category_indexing_spec.rb +2 -3
- data/spec/lib/category_spec.rb +10 -10
- data/spec/lib/character_substituters/west_european_spec.rb +6 -5
- data/spec/lib/cores_spec.rb +17 -17
- data/spec/lib/extensions/symbol_spec.rb +15 -1
- data/spec/lib/frontend_adapters/rack_spec.rb +20 -20
- data/spec/lib/generators/aliases_spec.rb +3 -3
- data/spec/lib/generators/cacher_strategy_spec.rb +1 -1
- data/spec/lib/generators/partial/default_spec.rb +3 -3
- data/spec/lib/generators/partial/none_spec.rb +2 -2
- data/spec/lib/generators/partial/substring_spec.rb +1 -1
- data/spec/lib/generators/partial_generator_spec.rb +3 -3
- data/spec/lib/generators/similarity/double_metaphone_spec.rb +1 -1
- data/spec/lib/generators/similarity/metaphone_spec.rb +1 -1
- data/spec/lib/generators/similarity/none_spec.rb +1 -1
- data/spec/lib/generators/similarity/phonetic_spec.rb +1 -1
- data/spec/lib/generators/similarity/soundex_spec.rb +1 -1
- data/spec/lib/generators/similarity_generator_spec.rb +2 -2
- data/spec/lib/generators/weights/logarithmic_spec.rb +1 -1
- data/spec/lib/generators/weights_generator_spec.rb +1 -1
- data/spec/lib/helpers/measuring_spec.rb +2 -2
- data/spec/lib/indexed/bundle/memory_spec.rb +6 -6
- data/spec/lib/indexed/bundle/redis_spec.rb +4 -4
- data/spec/lib/indexed/wrappers/bundle/calculation_spec.rb +2 -3
- data/spec/lib/indexed/wrappers/bundle/wrapper_spec.rb +2 -2
- data/spec/lib/indexed/wrappers/exact_first_spec.rb +5 -5
- data/spec/lib/indexers/base_spec.rb +1 -1
- data/spec/lib/indexers/parallel_spec.rb +1 -1
- data/spec/lib/indexers/serial_spec.rb +1 -1
- data/spec/lib/{index/base_indexed_spec.rb → indexes/index_indexed_spec.rb} +3 -3
- data/spec/lib/{index/base_indexing_spec.rb → indexes/index_indexing_spec.rb} +19 -2
- data/spec/lib/{index/base_spec.rb → indexes/index_spec.rb} +6 -25
- data/spec/lib/{index → indexes}/redis_spec.rb +1 -1
- data/spec/lib/indexes_class_spec.rb +2 -2
- data/spec/lib/indexes_indexed_spec.rb +1 -1
- data/spec/lib/indexes_indexing_spec.rb +1 -1
- data/spec/lib/indexes_spec.rb +1 -1
- data/spec/lib/indexing/bundle/base_spec.rb +7 -5
- data/spec/lib/indexing/bundle/memory_partial_generation_speed_spec.rb +4 -4
- data/spec/lib/indexing/bundle/memory_spec.rb +15 -15
- data/spec/lib/indexing/bundle/redis_spec.rb +9 -9
- data/spec/lib/interfaces/live_parameters_spec.rb +5 -5
- data/spec/lib/loader_spec.rb +17 -19
- data/spec/lib/loggers/search_spec.rb +2 -2
- data/spec/lib/query/allocation_spec.rb +1 -1
- data/spec/lib/query/allocations_spec.rb +1 -1
- data/spec/lib/query/combination_spec.rb +4 -4
- data/spec/lib/query/combinations/base_spec.rb +1 -1
- data/spec/lib/query/combinations/memory_spec.rb +1 -1
- data/spec/lib/query/combinations/redis_spec.rb +1 -1
- data/spec/lib/query/indexes_spec.rb +7 -2
- data/spec/lib/query/qualifier_category_mapper_spec.rb +34 -0
- data/spec/lib/query/token_spec.rb +32 -53
- data/spec/lib/query/tokens_spec.rb +30 -35
- data/spec/lib/query/weights_spec.rb +16 -16
- data/spec/lib/rack/harakiri_spec.rb +5 -5
- data/spec/lib/results_spec.rb +1 -1
- data/spec/lib/search_spec.rb +24 -22
- data/spec/lib/sinatra_spec.rb +36 -0
- data/spec/lib/sources/base_spec.rb +1 -1
- data/spec/lib/sources/couch_spec.rb +9 -9
- data/spec/lib/sources/csv_spec.rb +7 -7
- data/spec/lib/sources/db_spec.rb +2 -2
- data/spec/lib/sources/delicious_spec.rb +5 -5
- data/spec/lib/sources/mongo_spec.rb +7 -7
- data/spec/lib/sources/wrappers/base_spec.rb +2 -2
- data/spec/lib/sources/wrappers/location_spec.rb +1 -1
- data/spec/lib/statistics_spec.rb +1 -1
- data/spec/lib/tokenizers/base_spec.rb +2 -2
- data/spec/lib/tokenizers/index_spec.rb +1 -1
- data/spec/lib/tokenizers/query_spec.rb +1 -1
- metadata +30 -30
- data/lib/picky/adapters/rack/query.rb +0 -65
- data/lib/picky/index/base.rb +0 -409
- data/lib/picky/index/base_indexed.rb +0 -29
- data/lib/picky/index/base_indexing.rb +0 -127
- data/lib/picky/index/memory.rb +0 -16
- data/lib/picky/index/redis.rb +0 -16
- data/lib/picky/query/qualifiers.rb +0 -76
- data/lib/picky/query/solr.rb +0 -60
- data/lib/picky/signals.rb +0 -8
- data/lib/picky-tasks.rb +0 -6
- data/lib/tasks/spec.rake +0 -11
- data/spec/lib/query/qualifiers_spec.rb +0 -31
|
@@ -1,82 +1,86 @@
|
|
|
1
|
-
module
|
|
1
|
+
module Picky
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
# [token, index] [other_token, other_index], ...
|
|
5
|
-
#
|
|
6
|
-
class Allocation # :nodoc:all
|
|
3
|
+
module Query
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
#
|
|
5
|
+
# An allocation has a number of combinations:
|
|
6
|
+
# [token, index] [other_token, other_index], ...
|
|
11
7
|
#
|
|
12
|
-
|
|
13
|
-
@combinations = combinations
|
|
14
|
-
@result_identifier = result_identifier
|
|
15
|
-
end
|
|
8
|
+
class Allocation # :nodoc:all
|
|
16
9
|
|
|
17
|
-
|
|
18
|
-
@combinations.hash
|
|
19
|
-
end
|
|
20
|
-
def eql? other_allocation
|
|
21
|
-
true # FIXME
|
|
22
|
-
# @combinations.eql? other_allocation.combinations
|
|
23
|
-
end
|
|
10
|
+
attr_reader :count, :ids, :score, :combinations, :result_identifier
|
|
24
11
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
12
|
+
#
|
|
13
|
+
#
|
|
14
|
+
def initialize combinations, result_identifier
|
|
15
|
+
@combinations = combinations
|
|
16
|
+
@result_identifier = result_identifier
|
|
17
|
+
end
|
|
30
18
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
19
|
+
def hash
|
|
20
|
+
@combinations.hash
|
|
21
|
+
end
|
|
22
|
+
def eql? other_allocation
|
|
23
|
+
true # FIXME
|
|
24
|
+
# @combinations.eql? other_allocation.combinations
|
|
25
|
+
end
|
|
36
26
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
@ids = ids.slice!(offset, amount) || [] # slice out the relevant part
|
|
43
|
-
end
|
|
27
|
+
# Scores its combinations and caches the result.
|
|
28
|
+
#
|
|
29
|
+
def calculate_score weights
|
|
30
|
+
@score ||= @combinations.calculate_score(weights)
|
|
31
|
+
end
|
|
44
32
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
def remove identifiers = [] # categories
|
|
53
|
-
@combinations.remove identifiers
|
|
54
|
-
end
|
|
33
|
+
# Asks the combinations for the (intersected) ids.
|
|
34
|
+
#
|
|
35
|
+
def calculate_ids amount, offset
|
|
36
|
+
@combinations.ids amount, offset # Calculate as many ids as are necessary.
|
|
37
|
+
end
|
|
55
38
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
39
|
+
# This starts the searching process.
|
|
40
|
+
#
|
|
41
|
+
def process! amount, offset
|
|
42
|
+
ids = calculate_ids amount, offset
|
|
43
|
+
@count = ids.size # cache the count before throwing away the ids
|
|
44
|
+
@ids = ids.slice!(offset, amount) || [] # slice out the relevant part
|
|
45
|
+
end
|
|
61
46
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
47
|
+
#
|
|
48
|
+
#
|
|
49
|
+
def keep identifiers = [] # categories
|
|
50
|
+
@combinations.keep identifiers
|
|
51
|
+
end
|
|
52
|
+
#
|
|
53
|
+
#
|
|
54
|
+
def remove identifiers = [] # categories
|
|
55
|
+
@combinations.remove identifiers
|
|
56
|
+
end
|
|
67
57
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
58
|
+
# Sort highest score first.
|
|
59
|
+
#
|
|
60
|
+
def <=> other_allocation
|
|
61
|
+
other_allocation.score <=> self.score
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Transform the allocation into result form.
|
|
65
|
+
#
|
|
66
|
+
def to_result
|
|
67
|
+
[self.result_identifier, self.score, self.count, @combinations.to_result, self.ids] if self.count > 0
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Json representation of this allocation.
|
|
71
|
+
#
|
|
72
|
+
# Note: Delegates to to_result.
|
|
73
|
+
#
|
|
74
|
+
def to_json
|
|
75
|
+
to_result.to_json
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
#
|
|
79
|
+
#
|
|
80
|
+
def to_s
|
|
81
|
+
"Allocation(#{to_result})"
|
|
82
|
+
end
|
|
75
83
|
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
-
def to_s
|
|
79
|
-
"Allocation(#{to_result})"
|
|
80
84
|
end
|
|
81
85
|
|
|
82
86
|
end
|
|
@@ -1,112 +1,117 @@
|
|
|
1
|
-
module
|
|
2
|
-
# Container class for allocations.
|
|
3
|
-
#
|
|
4
|
-
class Allocations # :nodoc:all
|
|
1
|
+
module Picky
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
attr_reader :total
|
|
3
|
+
module Query
|
|
8
4
|
|
|
9
|
-
|
|
10
|
-
@allocations = allocations
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# Score each allocation.
|
|
5
|
+
# Container class for allocations.
|
|
14
6
|
#
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
7
|
+
class Allocations # :nodoc:all
|
|
8
|
+
|
|
9
|
+
delegate :each, :inject, :empty?, :size, :to => :@allocations
|
|
10
|
+
attr_reader :total
|
|
11
|
+
|
|
12
|
+
def initialize allocations = []
|
|
13
|
+
@allocations = allocations
|
|
18
14
|
end
|
|
19
|
-
end
|
|
20
|
-
# Sort the allocations.
|
|
21
|
-
#
|
|
22
|
-
def sort!
|
|
23
|
-
@allocations.sort!
|
|
24
|
-
end
|
|
25
15
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
16
|
+
# Score each allocation.
|
|
17
|
+
#
|
|
18
|
+
def calculate_score weights
|
|
19
|
+
@allocations.each do |allocation|
|
|
20
|
+
allocation.calculate_score weights
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
# Sort the allocations.
|
|
24
|
+
#
|
|
25
|
+
def sort!
|
|
26
|
+
@allocations.sort!
|
|
27
|
+
end
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
@allocations.each { |allocation| allocation.keep identifiers } unless identifiers.empty?
|
|
38
|
-
end
|
|
39
|
-
# Removes combinations.
|
|
40
|
-
#
|
|
41
|
-
# Only those passed in are removed.
|
|
42
|
-
#
|
|
43
|
-
def remove identifiers = []
|
|
44
|
-
@allocations.each { |allocation| allocation.remove identifiers } unless identifiers.empty?
|
|
45
|
-
end
|
|
29
|
+
# Reduces the amount of allocations to x.
|
|
30
|
+
#
|
|
31
|
+
def reduce_to amount
|
|
32
|
+
@allocations = @allocations.shift amount
|
|
33
|
+
end
|
|
46
34
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
35
|
+
# Keeps combinations.
|
|
36
|
+
#
|
|
37
|
+
# Only those passed in remain.
|
|
38
|
+
#
|
|
39
|
+
def keep identifiers = []
|
|
40
|
+
@allocations.each { |allocation| allocation.keep identifiers } unless identifiers.empty?
|
|
41
|
+
end
|
|
42
|
+
# Removes combinations.
|
|
43
|
+
#
|
|
44
|
+
# Only those passed in are removed.
|
|
45
|
+
#
|
|
46
|
+
def remove identifiers = []
|
|
47
|
+
@allocations.each { |allocation| allocation.remove identifiers } unless identifiers.empty?
|
|
52
48
|
end
|
|
53
|
-
end
|
|
54
49
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
# Parameters:
|
|
61
|
-
# * amount: the amount of ids to calculate
|
|
62
|
-
# * offset: the offset from where in the result set to take the ids
|
|
63
|
-
#
|
|
64
|
-
# Note: With an amount of 0, an offset > 0 doesn't make much
|
|
65
|
-
# sense, as seen in the live search.
|
|
66
|
-
#
|
|
67
|
-
# Note: Each allocation caches its count, but not its ids (thrown away).
|
|
68
|
-
# The ids are cached in this class.
|
|
69
|
-
#
|
|
70
|
-
# Note: It's possible that no ids are returned by an allocation, but a count. (In case of an offset)
|
|
71
|
-
#
|
|
72
|
-
def process! amount, offset = 0
|
|
73
|
-
@total = 0
|
|
74
|
-
current_offset = 0
|
|
75
|
-
@allocations.each do |allocation|
|
|
76
|
-
ids = allocation.process! amount, offset
|
|
77
|
-
@total = @total + allocation.count # the total mixed in
|
|
78
|
-
if ids.empty?
|
|
79
|
-
offset = offset - allocation.count unless offset.zero?
|
|
80
|
-
else
|
|
81
|
-
amount = amount - ids.size # we need less results from the following allocation
|
|
82
|
-
offset = 0 # we have already passed the offset
|
|
50
|
+
# Returns the top amount ids.
|
|
51
|
+
#
|
|
52
|
+
def ids amount = 20
|
|
53
|
+
@allocations.inject([]) do |total, allocation|
|
|
54
|
+
total.size >= amount ? (return total.shift(amount)) : total + allocation.ids
|
|
83
55
|
end
|
|
84
56
|
end
|
|
85
|
-
end
|
|
86
57
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
58
|
+
# This is the main method of this class that will replace ids and count.
|
|
59
|
+
#
|
|
60
|
+
# What it does is calculate the ids and counts of its allocations
|
|
61
|
+
# for being used in the results. It also calculates the total
|
|
62
|
+
#
|
|
63
|
+
# Parameters:
|
|
64
|
+
# * amount: the amount of ids to calculate
|
|
65
|
+
# * offset: the offset from where in the result set to take the ids
|
|
66
|
+
#
|
|
67
|
+
# Note: With an amount of 0, an offset > 0 doesn't make much
|
|
68
|
+
# sense, as seen in the live search.
|
|
69
|
+
#
|
|
70
|
+
# Note: Each allocation caches its count, but not its ids (thrown away).
|
|
71
|
+
# The ids are cached in this class.
|
|
72
|
+
#
|
|
73
|
+
# Note: It's possible that no ids are returned by an allocation, but a count. (In case of an offset)
|
|
74
|
+
#
|
|
75
|
+
def process! amount, offset = 0
|
|
76
|
+
@total = 0
|
|
77
|
+
current_offset = 0
|
|
78
|
+
@allocations.each do |allocation|
|
|
79
|
+
ids = allocation.process! amount, offset
|
|
80
|
+
@total = @total + allocation.count # the total mixed in
|
|
81
|
+
if ids.empty?
|
|
82
|
+
offset = offset - allocation.count unless offset.zero?
|
|
83
|
+
else
|
|
84
|
+
amount = amount - ids.size # we need less results from the following allocation
|
|
85
|
+
offset = 0 # we have already passed the offset
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
def uniq
|
|
91
|
+
@allocations.uniq!
|
|
92
|
+
end
|
|
94
93
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
94
|
+
def to_a
|
|
95
|
+
@allocations
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Simply inspects the internal allocations.
|
|
99
|
+
#
|
|
100
|
+
def to_s
|
|
101
|
+
@allocations.inspect
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Allocations for results are in the form:
|
|
105
|
+
# [
|
|
106
|
+
# allocation1.to_result,
|
|
107
|
+
# allocation2.to_result
|
|
108
|
+
# ...
|
|
109
|
+
# ]
|
|
110
|
+
#
|
|
111
|
+
def to_result
|
|
112
|
+
@allocations.map(&:to_result).compact
|
|
113
|
+
end
|
|
100
114
|
|
|
101
|
-
# Allocations for results are in the form:
|
|
102
|
-
# [
|
|
103
|
-
# allocation1.to_result,
|
|
104
|
-
# allocation2.to_result
|
|
105
|
-
# ...
|
|
106
|
-
# ]
|
|
107
|
-
#
|
|
108
|
-
def to_result
|
|
109
|
-
@allocations.map(&:to_result).compact
|
|
110
115
|
end
|
|
111
116
|
|
|
112
117
|
end
|
|
@@ -1,76 +1,80 @@
|
|
|
1
|
-
module
|
|
1
|
+
module Picky
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
# the index (the bundle): [text, index_bundle]
|
|
5
|
-
#
|
|
6
|
-
# A combination is a single part of an allocation:
|
|
7
|
-
# [..., [text2, index_bundle2], ...]
|
|
8
|
-
#
|
|
9
|
-
# An allocation consists of a number of combinations:
|
|
10
|
-
# [[text1, index_bundle1], [text2, index_bundle2], [text3, index_bundle1]]
|
|
11
|
-
#
|
|
12
|
-
class Combination # :nodoc:all
|
|
3
|
+
module Query
|
|
13
4
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def initialize token, category
|
|
17
|
-
@token = token
|
|
18
|
-
@category_name = category.name
|
|
19
|
-
@bundle = category.bundle_for token
|
|
20
|
-
@text = @token.text # don't want to use reset_similar already
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# Note: Required for uniq!
|
|
24
|
-
#
|
|
25
|
-
def hash
|
|
26
|
-
[@token.to_s, @bundle].hash
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# Returns the weight of this combination.
|
|
30
|
-
#
|
|
31
|
-
# Note: Caching is most of the time useful.
|
|
32
|
-
#
|
|
33
|
-
def weight
|
|
34
|
-
@weight ||= @bundle.weight(@text)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Returns an array of ids for the given text.
|
|
38
|
-
#
|
|
39
|
-
# Note: Caching is most of the time useful.
|
|
5
|
+
# Describes the combination of a token (the text) and
|
|
6
|
+
# the index (the bundle): [text, index_bundle]
|
|
40
7
|
#
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# The identifier for this combination.
|
|
8
|
+
# A combination is a single part of an allocation:
|
|
9
|
+
# [..., [text2, index_bundle2], ...]
|
|
46
10
|
#
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# Is the identifier in the given identifiers?
|
|
11
|
+
# An allocation consists of a number of combinations:
|
|
12
|
+
# [[text1, index_bundle1], [text2, index_bundle2], [text3, index_bundle1]]
|
|
52
13
|
#
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
14
|
+
class Combination # :nodoc:all
|
|
15
|
+
|
|
16
|
+
attr_reader :token, :bundle, :category_name
|
|
17
|
+
|
|
18
|
+
def initialize token, category
|
|
19
|
+
@token = token
|
|
20
|
+
@category_name = category.name
|
|
21
|
+
@bundle = category.bundle_for token
|
|
22
|
+
@text = @token.text # don't want to use reset_similar already
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Note: Required for uniq!
|
|
26
|
+
#
|
|
27
|
+
def hash
|
|
28
|
+
[@token.to_s, @bundle].hash
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Returns the weight of this combination.
|
|
32
|
+
#
|
|
33
|
+
# Note: Caching is most of the time useful.
|
|
34
|
+
#
|
|
35
|
+
def weight
|
|
36
|
+
@weight ||= @bundle.weight(@text)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Returns an array of ids for the given text.
|
|
40
|
+
#
|
|
41
|
+
# Note: Caching is most of the time useful.
|
|
42
|
+
#
|
|
43
|
+
def ids
|
|
44
|
+
@ids ||= @bundle.ids(@text)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# The identifier for this combination.
|
|
48
|
+
#
|
|
49
|
+
def identifier
|
|
50
|
+
"#{bundle.identifier}:#{@token.identifier}"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Is the identifier in the given identifiers?
|
|
54
|
+
#
|
|
55
|
+
def in? identifiers
|
|
56
|
+
identifiers.include? identifier
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Combines the category names with the original names.
|
|
60
|
+
# [
|
|
61
|
+
# [:title, 'Flarbl', :flarbl],
|
|
62
|
+
# [:category, 'Gnorf', :gnorf]
|
|
63
|
+
# ]
|
|
64
|
+
#
|
|
65
|
+
def to_result
|
|
66
|
+
[@category_name, *@token.to_result]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Example:
|
|
70
|
+
# "exact title:Peter*:peter"
|
|
71
|
+
#
|
|
72
|
+
def to_s
|
|
73
|
+
"#{bundle.identifier} #{to_result.join(':')}"
|
|
74
|
+
end
|
|
56
75
|
|
|
57
|
-
# Combines the category names with the original names.
|
|
58
|
-
# [
|
|
59
|
-
# [:title, 'Flarbl', :flarbl],
|
|
60
|
-
# [:category, 'Gnorf', :gnorf]
|
|
61
|
-
# ]
|
|
62
|
-
#
|
|
63
|
-
def to_result
|
|
64
|
-
[@category_name, *@token.to_result]
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Example:
|
|
68
|
-
# "exact title:Peter*:peter"
|
|
69
|
-
#
|
|
70
|
-
def to_s
|
|
71
|
-
"#{bundle.identifier} #{to_result.join(':')}"
|
|
72
76
|
end
|
|
73
|
-
|
|
77
|
+
|
|
74
78
|
end
|
|
75
79
|
|
|
76
80
|
end
|
|
@@ -1,66 +1,70 @@
|
|
|
1
|
-
module
|
|
1
|
+
module Picky
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
#
|
|
5
|
-
# They are the core of an allocation.
|
|
6
|
-
# An allocation consists of a number of combinations.
|
|
7
|
-
#
|
|
8
|
-
module Combinations # :nodoc:all
|
|
3
|
+
module Query
|
|
9
4
|
|
|
10
|
-
#
|
|
5
|
+
# Combinations are a number of Combination-s.
|
|
11
6
|
#
|
|
12
|
-
|
|
7
|
+
# They are the core of an allocation.
|
|
8
|
+
# An allocation consists of a number of combinations.
|
|
9
|
+
#
|
|
10
|
+
module Combinations # :nodoc:all
|
|
13
11
|
|
|
14
|
-
|
|
12
|
+
# Base Combinations contain methods for calculating score and ids.
|
|
13
|
+
#
|
|
14
|
+
class Base
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
attr_reader :combinations
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
@combinations = combinations
|
|
20
|
-
end
|
|
18
|
+
delegate :empty?, :to => :@combinations
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
def initialize combinations = []
|
|
21
|
+
@combinations = combinations
|
|
22
|
+
end
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
total_score + weighted_score(weights)
|
|
30
|
-
end
|
|
31
|
-
def total_score
|
|
32
|
-
@combinations.sum &:weight
|
|
33
|
-
end
|
|
34
|
-
def weighted_score weights
|
|
35
|
-
weights.score @combinations
|
|
36
|
-
end
|
|
24
|
+
def hash
|
|
25
|
+
@combinations.hash
|
|
26
|
+
end
|
|
37
27
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
28
|
+
# Uses user specific weights to calculate a score for the combinations.
|
|
29
|
+
#
|
|
30
|
+
def calculate_score weights
|
|
31
|
+
total_score + weighted_score(weights)
|
|
32
|
+
end
|
|
33
|
+
def total_score
|
|
34
|
+
@combinations.sum &:weight
|
|
35
|
+
end
|
|
36
|
+
def weighted_score weights
|
|
37
|
+
weights.score @combinations
|
|
38
|
+
end
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
40
|
+
# Filters the tokens and identifiers such that only identifiers
|
|
41
|
+
# that are passed in, remain, including their tokens.
|
|
42
|
+
#
|
|
43
|
+
# Note: This method is not totally independent of the calculate_ids one.
|
|
44
|
+
# Since identifiers are only nullified, we need to not include the
|
|
45
|
+
# ids that have an associated identifier that is nil.
|
|
46
|
+
#
|
|
47
|
+
def keep identifiers = []
|
|
48
|
+
@combinations.reject! { |combination| !combination.in?(identifiers) }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Filters the tokens and identifiers such that identifiers
|
|
52
|
+
# that are passed in, are removed, including their tokens.
|
|
53
|
+
#
|
|
54
|
+
# Note: This method is not totally independent of the calculate_ids one.
|
|
55
|
+
# Since identifiers are only nullified, we need to not include the
|
|
56
|
+
# ids that have an associated identifier that is nil.
|
|
57
|
+
#
|
|
58
|
+
def remove identifiers = []
|
|
59
|
+
@combinations.reject! { |combination| combination.in?(identifiers) }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
#
|
|
63
|
+
#
|
|
64
|
+
def to_result
|
|
65
|
+
@combinations.map &:to_result
|
|
66
|
+
end
|
|
59
67
|
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
def to_result
|
|
63
|
-
@combinations.map &:to_result
|
|
64
68
|
end
|
|
65
69
|
|
|
66
70
|
end
|