picky 4.12.4 → 4.12.5

Sign up to get free protection for your applications and to get access to all the features.
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