picky 4.12.4 → 4.12.5

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/loader.rb CHANGED
@@ -173,7 +173,7 @@ module Picky
173
173
  load_relative 'query/boosts'
174
174
 
175
175
  load_relative 'query/indexes',
176
- 'query/indexes_check'
176
+ 'query/indexes/check'
177
177
  end
178
178
 
179
179
  # Loads the internal parts of the framework.
@@ -37,10 +37,10 @@ module Picky
37
37
  # ignored (ie. removed).
38
38
  #
39
39
  def calculate_score weights
40
- @score ||= if @combinations.empty?
40
+ @score ||= if @combinations.empty?
41
41
  0 # Optimization.
42
- else
43
- @backend.weight(@combinations) + @combinations.boost_for(weights)
42
+ else
43
+ @backend.weight(@combinations) + @combinations.boost_for(weights)
44
44
  end
45
45
  end
46
46
 
@@ -113,6 +113,12 @@ module Picky
113
113
  def to_json options = {}
114
114
  MultiJson.encode to_result, options
115
115
  end
116
+
117
+ #
118
+ #
119
+ def to_qualifiers
120
+ @combinations.to_qualifiers
121
+ end
116
122
 
117
123
  #
118
124
  #
@@ -46,13 +46,46 @@ module Picky
46
46
  @allocations = @allocations.shift amount
47
47
  end
48
48
 
49
- # Removes combinations.
49
+ # Removes categories from allocations.
50
50
  #
51
51
  # Only those passed in are removed.
52
52
  #
53
- def remove categories = []
53
+ def remove_categories categories = []
54
54
  @allocations.each { |allocation| allocation.remove categories } unless categories.empty?
55
55
  end
56
+
57
+ # Removes allocations.
58
+ #
59
+ # Only those passed in are removed.
60
+ #
61
+ # TODO Rewrite, speed up.
62
+ #
63
+ def remove_allocations qualifiers_array = []
64
+ return if qualifiers_array.empty?
65
+ @allocations.select! do |allocation|
66
+ allocation_qualifiers = allocation.combinations.to_qualifiers
67
+ next(false) if qualifiers_array.any? do |qualifiers|
68
+ allocation_qualifiers == qualifiers
69
+ end
70
+ allocation
71
+ end
72
+ end
73
+
74
+ # Keeps allocations.
75
+ #
76
+ # Only those passed in are kept.
77
+ #
78
+ # TODO Rewrite, speed up.
79
+ #
80
+ def keep_allocations qualifiers_array = []
81
+ return if qualifiers_array.empty?
82
+ @allocations.select! do |allocation|
83
+ allocation_qualifiers = allocation.combinations.to_qualifiers
84
+ next(true) if qualifiers_array.any? do |qualifiers|
85
+ allocation_qualifiers == qualifiers
86
+ end
87
+ end
88
+ end
56
89
 
57
90
  # Returns the top amount ids.
58
91
  #
@@ -49,6 +49,10 @@ module Picky
49
49
  def to_result
50
50
  @combinations.map &:to_result
51
51
  end
52
+
53
+ def to_qualifiers
54
+ @combinations.map &:category_name
55
+ end
52
56
 
53
57
  #
54
58
  #
@@ -0,0 +1,51 @@
1
+ module Picky
2
+
3
+ module Query
4
+
5
+ class Indexes
6
+
7
+ #
8
+ #
9
+ class Check
10
+
11
+ class << self
12
+
13
+ # Returns the right combinations strategy for
14
+ # a number of query indexes.
15
+ #
16
+ # Currently it isn't possible using Memory and Redis etc.
17
+ # indexes in the same query index group.
18
+ #
19
+ # Picky will raise a Query::Indexes::DifferentBackendsError.
20
+ #
21
+ def check_backends indexes
22
+ backends = indexes.map &:backend
23
+ backends.uniq! &:class
24
+ raise_different backends if backends.size > 1
25
+ backends
26
+ end
27
+ def raise_different backends
28
+ raise DifferentBackendsError.new(backends)
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ # Currently it isn't possible using Memory and Redis etc.
36
+ # indexes in the same query index group.
37
+ #
38
+ class DifferentBackendsError < StandardError
39
+ def initialize backends
40
+ @backends = backends
41
+ end
42
+ def to_s
43
+ "Currently it isn't possible to mix Indexes with backends #{@backends.join(" and ")} in the same Search instance."
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -16,7 +16,9 @@ module Picky
16
16
  forward :size, :first, :to => :@indexes
17
17
 
18
18
  attr_reader :indexes,
19
- :ignored_categories
19
+ :ignored_categories,
20
+ :ignored_allocations,
21
+ :exclusive_allocations
20
22
 
21
23
  # Creates a new Query::Indexes.
22
24
  #
@@ -24,27 +26,39 @@ module Picky
24
26
  # Note: We cannot mix memory and redis indexes just yet.
25
27
  #
26
28
  def initialize *indexes
27
- IndexesCheck.check_backends indexes
29
+ Check.check_backends indexes
28
30
 
29
31
  @indexes = indexes
30
32
  end
31
33
 
32
- # TODO Reinstate.
33
- #
34
- # # Ignore the categories with these qualifiers.
35
- # #
36
- # # Example:
37
- # # search = Search.new(index1, index2, index3) do
38
- # # ignore :name, :first_name
39
- # # end
40
- # #
41
- # # Note: Cleans up / optimizes after being called.
42
- # #
43
- # def ignore *qualifiers
44
- # @ignored_categories ||= []
45
- # @ignored_categories += qualifiers.map { |qualifier| @qualifier_mapper.map qualifier }.compact
46
- # @ignored_categories.uniq!
47
- # end
34
+ # Ignore the categories with the given qualifiers.
35
+ #
36
+ def ignore_categories *qualifiers
37
+ @ignored_categories ||= []
38
+ # @ignored_categories += qualifiers.map { |qualifier| @qualifier_mapper.map qualifier }.compact
39
+ @ignored_categories += qualifiers
40
+ @ignored_categories.uniq!
41
+ end
42
+
43
+ # Ignore the allocations with the given qualifiers.
44
+ #
45
+ def ignore_allocations *qualifier_arrays
46
+ @ignored_allocations ||= []
47
+ @ignored_allocations += qualifier_arrays #.map do |qualifier_array|
48
+ # qualifier_array.map { |qualifier| @qualifier_mapper.map qualifier }
49
+ # end.compact
50
+ @ignored_allocations.uniq!
51
+ end
52
+
53
+ # Exclusively keep the allocations with the given qualifiers.
54
+ #
55
+ def keep_allocations *qualifier_arrays
56
+ @exclusive_allocations ||= []
57
+ @exclusive_allocations += qualifier_arrays #.map do |qualifier_array|
58
+ # qualifier_array.map { |qualifier| @qualifier_mapper.map qualifier }
59
+ # end.compact
60
+ @exclusive_allocations.uniq!
61
+ end
48
62
 
49
63
  # Returns a number of prepared (sorted, reduced etc.) allocations for the given tokens.
50
64
  #
@@ -57,13 +71,20 @@ module Picky
57
71
  #
58
72
  allocations.calculate_score weights
59
73
 
74
+ # Filter the allocations – ignore/only.
75
+ #
76
+ allocations.keep_allocations exclusive_allocations if exclusive_allocations
77
+ allocations.remove_allocations ignored_allocations if ignored_allocations
78
+
60
79
  # Sort the allocations.
61
80
  # (allocations are sorted according to score, highest to lowest)
62
81
  #
63
82
  # Before we can chop off unimportant allocations, we need to sort them.
64
83
  #
65
84
  allocations.sort!
66
-
85
+
86
+ # allocations.remove_allocations ignored_allocations if ignored_allocations
87
+
67
88
  # Reduce the amount of allocations.
68
89
  #
69
90
  # Before we remove categories, we should reduce the amount of allocations.
@@ -72,7 +93,7 @@ module Picky
72
93
 
73
94
  # Remove categories from allocations.
74
95
  #
75
- allocations.remove ignored_categories if ignored_categories
96
+ allocations.remove_categories ignored_categories if ignored_categories
76
97
 
77
98
  allocations
78
99
  end
data/lib/picky/search.rb CHANGED
@@ -23,9 +23,7 @@ module Picky
23
23
  attr_accessor :tokenizer,
24
24
  :boosts
25
25
 
26
- forward :ignore,
27
- :only,
28
- :remap_qualifiers,
26
+ forward :remap_qualifiers,
29
27
  :to => :indexes
30
28
 
31
29
  # Takes:
@@ -140,7 +138,40 @@ module Picky
140
138
  def boost boosts
141
139
  @boosts = extract_boosts boosts
142
140
  end
143
-
141
+
142
+ # Ignore given categories and/or combinations of
143
+ # categories.
144
+ #
145
+ # Example:
146
+ # search = Search.new(people) do
147
+ # ignore :name,
148
+ # :first_name
149
+ # [:last_name, :street]
150
+ # end
151
+ #
152
+ def ignore *allocations_and_categories
153
+ allocations_and_categories.each do |allocation_or_category|
154
+ if allocation_or_category.respond_to? :to_sym
155
+ indexes.ignore_categories allocation_or_category
156
+ else
157
+ indexes.ignore_allocations allocation_or_category
158
+ end
159
+ end
160
+ end
161
+
162
+ # Exclusively keep combinations of
163
+ # categories.
164
+ #
165
+ # Example:
166
+ # search = Search.new(people) do
167
+ # only [:last_name, :street],
168
+ # [:last_name, :first_name]
169
+ # end
170
+ #
171
+ def only *allocations_and_categories
172
+ indexes.keep_allocations *allocations_and_categories
173
+ end
174
+
144
175
  # Ignore the given token if it cannot be matched to a category.
145
176
  # The default behaviour is that if a token does not match to
146
177
  # any category, the query will not return anything (since a
@@ -0,0 +1,70 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ # Shows that lists of categories can be ignored.
6
+ #
7
+ describe 'ignoring allocations/categories' do
8
+
9
+ it 'ignores allocations correctly' do
10
+ index = Picky::Index.new :books do
11
+ category :author
12
+ category :title
13
+ category :text
14
+ end
15
+
16
+ thing = Struct.new :id, :author, :title, :text
17
+ index.add thing.new(1, 'peter', 'some title', 'some text')
18
+ index.add thing.new(2, 'some name', 'some title', 'some text')
19
+
20
+ try = Picky::Search.new index do
21
+ ignore [:author, :text],
22
+ [:text, :text]
23
+ end
24
+
25
+ # These allocations are now removed.
26
+ #
27
+ try.search('some some').allocations.to_result.should == [
28
+ # [:books, 1.386, 2, [[:text, "some", "some"], [:text, "some", "some"]], [2, 1]],
29
+ [:books, 1.386, 2, [[:text, "some", "some"], [:title, "some", "some"]], [2, 1]],
30
+ [:books, 1.386, 2, [[:title, "some", "some"], [:text, "some", "some"]], [2, 1]],
31
+ [:books, 1.386, 2, [[:title, "some", "some"], [:title, "some", "some"]], [2, 1]],
32
+ [:books, 0.693, 1, [[:title, "some", "some"], [:author, "some", "some"]], [2]],
33
+ # [:books, 0.693, 1, [[:author, "some", "some"], [:text, "some", "some"]], [2]],
34
+ [:books, 0.693, 1, [[:author, "some", "some"], [:title, "some", "some"]], [2]],
35
+ [:books, 0.693, 1, [[:text, "some", "some"], [:author, "some", "some"]], [2]],
36
+ [:books, 0.0, 1, [[:author, "some", "some"], [:author, "some", "some"]], [2]]
37
+ ]
38
+ end
39
+
40
+ it 'keeps allocations correctly' do
41
+ index = Picky::Index.new :books do
42
+ category :author
43
+ category :title
44
+ category :text
45
+ end
46
+
47
+ thing = Struct.new :id, :author, :title, :text
48
+ index.add thing.new(1, 'peter', 'some title', 'some text')
49
+ index.add thing.new(2, 'some name', 'some title', 'some text')
50
+
51
+ try = Picky::Search.new index do
52
+ only [:author, :text],
53
+ [:text, :text]
54
+ end
55
+
56
+ # These allocations are now exclusively kept.
57
+ #
58
+ try.search('some some').allocations.to_result.should == [
59
+ [:books, 1.386, 2, [[:text, "some", "some"], [:text, "some", "some"]], [2, 1]],
60
+ # [:books, 1.386, 2, [[:text, "some", "some"], [:title, "some", "some"]], [2, 1]],
61
+ # [:books, 1.386, 2, [[:title, "some", "some"], [:text, "some", "some"]], [2, 1]],
62
+ # [:books, 1.386, 2, [[:title, "some", "some"], [:title, "some", "some"]], [2, 1]],
63
+ # [:books, 0.693, 1, [[:title, "some", "some"], [:author, "some", "some"]], [2]],
64
+ [:books, 0.693, 1, [[:author, "some", "some"], [:text, "some", "some"]], [2]],
65
+ # [:books, 0.693, 1, [[:author, "some", "some"], [:title, "some", "some"]], [2]],
66
+ # [:books, 0.693, 1, [[:text, "some", "some"], [:author, "some", "some"]], [2]],
67
+ # [:books, 0.0, 1, [[:author, "some", "some"], [:author, "some", "some"]], [2]]
68
+ ]
69
+ end
70
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ # Shows that lists of categories can be ignored.
6
+ #
7
+ describe 'ignoring allocations' do
8
+
9
+ it 'works' do
10
+ index = Picky::Index.new :books do
11
+ category :author
12
+ category :title
13
+ category :text
14
+ end
15
+
16
+ thing = Struct.new :id, :author, :title, :text
17
+ index.add thing.new(1, 'peter', 'some title', 'some text')
18
+ index.add thing.new(2, 'some name', 'some title', 'some text')
19
+
20
+ try = Picky::Search.new index do
21
+ ignore [:author, :text],
22
+ [:text, :text]
23
+ end
24
+
25
+ # These allocations are now removed.
26
+ #
27
+ try.search('some some').allocations.to_result.should == [
28
+ # [:books, 1.386, 2, [[:text, "some", "some"], [:text, "some", "some"]], [2, 1]],
29
+ [:books, 1.386, 2, [[:text, "some", "some"], [:title, "some", "some"]], [2, 1]],
30
+ [:books, 1.386, 2, [[:title, "some", "some"], [:text, "some", "some"]], [2, 1]],
31
+ [:books, 1.386, 2, [[:title, "some", "some"], [:title, "some", "some"]], [2, 1]],
32
+ [:books, 0.693, 1, [[:title, "some", "some"], [:author, "some", "some"]], [2]],
33
+ # [:books, 0.693, 1, [[:author, "some", "some"], [:text, "some", "some"]], [2]],
34
+ [:books, 0.693, 1, [[:author, "some", "some"], [:title, "some", "some"]], [2]],
35
+ [:books, 0.693, 1, [[:text, "some", "some"], [:author, "some", "some"]], [2]],
36
+ [:books, 0.0, 1, [[:author, "some", "some"], [:author, "some", "some"]], [2]]
37
+ ]
38
+ end
39
+ end
@@ -28,7 +28,7 @@ describe Picky::Query::Allocations do
28
28
  @allocation1.should_receive(:remove).never
29
29
  @allocation2.should_receive(:remove).never
30
30
 
31
- @allocations.remove
31
+ @allocations.remove_categories
32
32
  end
33
33
  end
34
34
  context 'categories not empty' do
@@ -37,7 +37,7 @@ describe Picky::Query::Allocations do
37
37
  @allocation2.should_receive(:remove).once.with :some_category
38
38
  @allocation3.should_receive(:remove).once.with :some_category
39
39
 
40
- @allocations.remove :some_category
40
+ @allocations.remove_categories :some_category
41
41
  end
42
42
  end
43
43
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Picky::Query::IndexesCheck do
3
+ describe Picky::Query::Indexes::Check do
4
4
 
5
5
  describe 'check_backend_types' do
6
6
  backends = [
@@ -25,7 +25,7 @@ describe Picky::Query::IndexesCheck do
25
25
  it 'raises on multiple types' do
26
26
  expect do
27
27
  described_class.check_backends [index1, index2]
28
- end.to raise_error(Picky::Query::DifferentBackendsError)
28
+ end.to raise_error(Picky::Query::Indexes::DifferentBackendsError)
29
29
  end
30
30
  it 'raises with the right message on multiple types' do
31
31
  expect do
@@ -41,7 +41,7 @@ describe Picky::Query::IndexesCheck do
41
41
  it 'raises on multiple types' do
42
42
  expect do
43
43
  described_class.check_backends [index1, index2, index3]
44
- end.to raise_error(Picky::Query::DifferentBackendsError)
44
+ end.to raise_error(Picky::Query::Indexes::DifferentBackendsError)
45
45
  end
46
46
  it 'raises with the right message on multiple types' do
47
47
  expect do
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe Picky::Query::Indexes do
4
4
 
5
5
  before(:each) do
6
- Picky::Query::IndexesCheck.stub! :check_backends
6
+ Picky::Query::Indexes::Check.stub! :check_backends
7
7
  end
8
8
 
9
9
  3.times do |i|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: picky
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.12.4
4
+ version: 4.12.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-06 00:00:00.000000000 Z
12
+ date: 2012-12-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 4.12.4
37
+ version: 4.12.5
38
38
  type: :development
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 4.12.4
45
+ version: 4.12.5
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: text
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -231,8 +231,8 @@ files:
231
231
  - lib/picky/query/boosts.rb
232
232
  - lib/picky/query/combination.rb
233
233
  - lib/picky/query/combinations.rb
234
+ - lib/picky/query/indexes/check.rb
234
235
  - lib/picky/query/indexes.rb
235
- - lib/picky/query/indexes_check.rb
236
236
  - lib/picky/query/token.rb
237
237
  - lib/picky/query/tokens.rb
238
238
  - lib/picky/rack/harakiri.rb
@@ -280,9 +280,11 @@ files:
280
280
  - spec/functional/dynamic_weights_spec.rb
281
281
  - spec/functional/exact_first_spec.rb
282
282
  - spec/functional/facets_spec.rb
283
+ - spec/functional/ignore_spec.rb
283
284
  - spec/functional/max_allocations_spec.rb
284
285
  - spec/functional/multi_index_qualifier_spec.rb
285
286
  - spec/functional/non_specific_ids_larger_than_20_spec.rb
287
+ - spec/functional/only_allocations_spec.rb
286
288
  - spec/functional/only_spec.rb
287
289
  - spec/functional/pool_spec.rb
288
290
  - spec/functional/range_queries_spec.rb
@@ -446,9 +448,11 @@ test_files:
446
448
  - spec/functional/dynamic_weights_spec.rb
447
449
  - spec/functional/exact_first_spec.rb
448
450
  - spec/functional/facets_spec.rb
451
+ - spec/functional/ignore_spec.rb
449
452
  - spec/functional/max_allocations_spec.rb
450
453
  - spec/functional/multi_index_qualifier_spec.rb
451
454
  - spec/functional/non_specific_ids_larger_than_20_spec.rb
455
+ - spec/functional/only_allocations_spec.rb
452
456
  - spec/functional/only_spec.rb
453
457
  - spec/functional/pool_spec.rb
454
458
  - spec/functional/range_queries_spec.rb
@@ -1,45 +0,0 @@
1
- module Picky
2
-
3
- module Query
4
-
5
- class IndexesCheck
6
-
7
- class << self
8
-
9
- # Returns the right combinations strategy for
10
- # a number of query indexes.
11
- #
12
- # Currently it isn't possible using Memory and Redis etc.
13
- # indexes in the same query index group.
14
- #
15
- # Picky will raise a Query::Indexes::DifferentBackendsError.
16
- #
17
- def check_backends indexes
18
- backends = indexes.map &:backend
19
- backends.uniq! &:class
20
- raise_different backends if backends.size > 1
21
- backends
22
- end
23
- def raise_different backends
24
- raise DifferentBackendsError.new(backends)
25
- end
26
-
27
- end
28
-
29
- end
30
-
31
- # Currently it isn't possible using Memory and Redis etc.
32
- # indexes in the same query index group.
33
- #
34
- class DifferentBackendsError < StandardError
35
- def initialize backends
36
- @backends = backends
37
- end
38
- def to_s
39
- "Currently it isn't possible to mix Indexes with backends #{@backends.join(" and ")} in the same Search instance."
40
- end
41
- end
42
-
43
- end
44
-
45
- end