picky 4.16.0 → 4.17.0

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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NjVkMTA4OTYyYzkyZTMzZjAxYjM3YWRlMGQwMGE2MDc4Zjc3NDA4Nw==
4
+ NWY4NDk4ZTVlNThhMDQwZDk5OGJmZTk4MmQ0OGJjNDBmNDQzNDIzMA==
5
5
  data.tar.gz: !binary |-
6
- NDBiYmEzNWJlNDE3OTNkMmVhODU3NWYyY2QyZTQ4ZTdiN2RmZTA5Mg==
6
+ NDFhZmZkYmYzYWZiMWZiNjY4OTViNWU4NzZmNDAxZjcxMDY3Y2MwMQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- YmQ3MzczYTdmZjFlOTMwYmQ3ZjY3ZTkwMzBiMjU2MTUzMGQyZmM1ZjNkODg2
10
- NGFjMTc0NzQ3MDRiZGQ3ZjY1ZGY3MzNlYjMyY2FkNTJmZWNlMzg2YWE0NWEx
11
- Njk5NWQzYmI2OWVmMWM0NTMyZTliZGUwMTE2NDdmZWI4NzVlMGQ=
9
+ ZGFhMjViOGEzNDE1Y2FlYzRmNWE1ZTBjYTk5ZmI4NDY4Njg5MTE1MjFhZWRl
10
+ MGUyODdkMTljZTIzNjg1MThmMGJkOTMwZWJiYWJiZWQzMGJlNjc3ZDNmMTM5
11
+ ZDNmOWQ4ZjQyYWQ1ZDA1MjQ1NzEwMDJlYzcyYWM3YjkzOTIxYTc=
12
12
  data.tar.gz: !binary |-
13
- NGRmYmE3OTMxOTE0NmY3OTY2NThhMTdhNDI1YzQ5OTQ3ZDhlZjhmNjEzMmEw
14
- NjcyNGIyYTVjYjdkNzU3NTFhNTZkN2M1YzdiMDBiOWNlMmQ5YTBmZDFiMjRk
15
- MTFkZGIwOThmNmEzOTRjODRlMDVlMzYyMTEyYjI5ZTcwOTkwYTA=
13
+ N2Y1MWRkNmZiNWZiNzYzYjU2YWM5ZjI5ZWQzYTIwOGQ2MGM1ZTg2ZjU4ZWQ5
14
+ OWQ0N2IyMzM4YjRmNTk2ZjY3NTJmMzM0ZTQzOGUwMjRiODI5NmFlMjIzMzUx
15
+ M2I3MDZjODUxYWQyODBjNTU2YTNhYTdjNTE3YmVlZGU3MWI1MjQ=
data/lib/picky/bundle.rb CHANGED
@@ -54,7 +54,6 @@ module Picky
54
54
  @partial_strategy = partial_strategy
55
55
  @similarity_strategy = similarity_strategy
56
56
 
57
- @key_format = options.delete :key_format
58
57
  @backend = options.delete :backend
59
58
 
60
59
  reset_backend
@@ -146,10 +145,10 @@ module Picky
146
145
 
147
146
  # If a key format is set, use it, else forward to the category.
148
147
  #
149
- # TODO What about setting the key_format per category?
148
+ # TODO Removed optimisation: @key_format ||= @category.key_format
150
149
  #
151
150
  def key_format
152
- @key_format || @category.key_format
151
+ @category.key_format
153
152
  end
154
153
 
155
154
  # Path and partial filename of a specific subindex.
@@ -2,17 +2,9 @@ module Picky
2
2
 
3
3
  class Categories
4
4
 
5
- each_forward :load, :analyze, :to => :categories
6
-
7
- # Return all possible combinations for the given token.
8
- #
9
- # This checks if it needs to also search through similar
10
- # tokens, if for example, the token is one with ~.
11
- # If yes, it puts together all solutions.
12
- #
13
- def possible_combinations token
14
- token.similar? ? similar_possible_for(token) : possible_for(token)
15
- end
5
+ each_forward :load,
6
+ :analyze,
7
+ :to => :categories
16
8
 
17
9
  # Gets all similar tokens and puts together the possible combinations
18
10
  # for each found similar token.
@@ -46,7 +38,7 @@ module Picky
46
38
  #
47
39
  def possible_for token, preselected_categories = nil
48
40
  (preselected_categories || possible_categories(token)).inject([]) do |combinations, category|
49
- combination = category.combination_for token
41
+ combination = token.combination_for category
50
42
  combination ? combinations << combination : combinations
51
43
  end
52
44
  end
@@ -85,7 +85,7 @@ module Picky
85
85
  warn <<-WARNING if options && (options.keys - @@known_keys).size > 0
86
86
 
87
87
  Warning: Category options #{options} for category #{name} contain an unknown option.
88
- Working options are: #{@@known_keys}.
88
+ Working options are: #@@known_keys.
89
89
  WARNING
90
90
  end
91
91
  def weights_from options
@@ -21,7 +21,7 @@ module Picky
21
21
  # TODO We might be able to return early?
22
22
  #
23
23
  @ranger.new(*range).inject(nil) do |sum, text|
24
- weight = bundle.weight(text)
24
+ weight = bundle.weight text
25
25
  weight && (weight + (sum || 0)) || sum
26
26
  end
27
27
  else
@@ -55,15 +55,6 @@ module Picky
55
55
  token.partial? ? partial : exact
56
56
  end
57
57
 
58
- # Returns a combination for the token,
59
- # or nil, if there is none.
60
- #
61
- # TODO Don't throw away the weight, instead store it in the combination?
62
- #
63
- def combination_for token
64
- weight(token) && Query::Combination.new(token, self)
65
- end
66
-
67
58
  end
68
59
 
69
60
  end
@@ -56,7 +56,8 @@ module Picky
56
56
  # generates the necessary derived indexes.
57
57
  #
58
58
  def retrieve
59
- prepared.retrieve { |id, token| add_tokenized_token id, token, :<< }
59
+ format = key_format?
60
+ prepared.retrieve { |id, token| add_tokenized_token id, token, :<<, format }
60
61
  end
61
62
 
62
63
  # Return the key format.
@@ -65,10 +66,11 @@ module Picky
65
66
  # and the source has no key format, ask
66
67
  # the index for one.
67
68
  #
68
- # Default is to_i.
69
- #
70
69
  def key_format
71
- @key_format ||= @index.key_format || :to_i
70
+ @key_format ||= @index.key_format
71
+ end
72
+ def key_format?
73
+ key_format
72
74
  end
73
75
 
74
76
  # Where the data is taken from.
@@ -8,7 +8,7 @@ module Picky
8
8
  # given id.
9
9
  #
10
10
  def remove id
11
- id = id.send key_format
11
+ id = id.send key_format if key_format?
12
12
  exact.remove id
13
13
  partial.remove id
14
14
  end
@@ -42,7 +42,7 @@ module Picky
42
42
  return unless text = hash[from] || hash[from.to_s]
43
43
 
44
44
  raise IdNotGivenException.new unless id = hash[:id] || hash['id']
45
- id = id.send key_format
45
+ id = id.send key_format if key_format?
46
46
 
47
47
  remove id
48
48
  add_text id, text
@@ -72,11 +72,9 @@ module Picky
72
72
  tokens = text_or_tokens
73
73
  end
74
74
 
75
- # TODO Have an "as is" key_format?
76
- #
77
- tokens.each { |text| add_tokenized_token id.send(key_format), text, where, false }
75
+ format = self.key_format?
76
+ tokens.each { |text| add_tokenized_token id, text, where, format }
78
77
  rescue NoMethodError
79
- # TODO This also is raised on a wrong key_format.
80
78
  # TODO Improve error message by pointing out what exactly goes wrong: thing xy does not have an #each method.
81
79
  raise %Q{You probably set tokenize: false on category "#{name}". It will need an Enumerator of previously tokenized tokens.}
82
80
  end
@@ -85,12 +83,15 @@ module Picky
85
83
  #
86
84
  def add_tokenized_token id, text, where = :unshift, format = true
87
85
  return unless text
88
-
86
+
89
87
  id = id.send key_format if format
90
88
  # text = text.to_sym if @symbols # SYMBOLS.
91
89
 
92
90
  exact.add id, text, where
93
91
  partial.add_partialized id, text, where
92
+ rescue NoMethodError => e
93
+ puts e.message
94
+ raise %Q{The object id with text "#{text}" does not respond to method #{key_format}.}
94
95
  end
95
96
 
96
97
  # Clears the realtime mapping.
data/lib/picky/index.rb CHANGED
@@ -378,7 +378,7 @@ INDEX
378
378
  #
379
379
  #
380
380
  def to_s
381
- "#{self.class}(#{name}, result_id: #{result_identifier}, source: #{@source}, categories: #{categories})"
381
+ "#{self.class}(#{name}, result_id: #{result_identifier}, source: #@source, categories: #{categories})"
382
382
  end
383
383
 
384
384
  end
@@ -7,7 +7,6 @@ module Picky
7
7
  forward :load,
8
8
  :analyze,
9
9
  :reindex,
10
- :possible_combinations,
11
10
  :to => :categories
12
11
 
13
12
  # Define how the results of this index are identified.
data/lib/picky/loader.rb CHANGED
@@ -164,7 +164,8 @@ module Picky
164
164
  #
165
165
  def load_query
166
166
  load_relative 'query/combination',
167
- 'query/combinations'
167
+ 'query/combinations',
168
+ 'query/combination/or'
168
169
 
169
170
  load_relative 'query/allocation',
170
171
  'query/allocations'
@@ -190,6 +191,7 @@ module Picky
190
191
  load_wrappers
191
192
  load_relative 'query/token' # Token related.
192
193
  load_relative 'query/tokens'
194
+ load_relative 'query/or'
193
195
  load_query
194
196
  end
195
197
 
@@ -74,7 +74,7 @@ module Picky
74
74
  # configured weights.
75
75
  #
76
76
  def to_s
77
- "#{self.class}(#{@boosts})"
77
+ "#{self.class}(#@boosts)"
78
78
  end
79
79
 
80
80
  end
@@ -2,22 +2,27 @@ module Picky
2
2
 
3
3
  module Query
4
4
 
5
- # Describes the Combination of a Token (the text) and
6
- # the index (the bundle): [text, index_bundle].
5
+ # Describes the Combination of:
6
+ # * a token
7
+ # * a category
8
+ # * the weight of the token in the category (cached)
7
9
  #
8
10
  # An Allocation consists of an ordered number of Combinations.
9
11
  #
10
12
  class Combination
11
13
 
12
14
  attr_reader :token,
13
- :category
15
+ :category,
16
+ :weight
14
17
 
15
- def initialize token, category
18
+ def initialize token, category, weight
16
19
  @token = token
17
20
  @category = category
21
+ @weight = weight
18
22
  end
19
23
 
20
24
  # Returns the category's name.
25
+ # Used in boosting.
21
26
  #
22
27
  def category_name
23
28
  @category_name ||= category.name
@@ -31,10 +36,8 @@ module Picky
31
36
 
32
37
  # Returns the weight of this combination.
33
38
  #
34
- # Note: Caching is most of the time useful.
35
- #
36
39
  def weight
37
- @weight ||= category.weight(token)
40
+ @weight
38
41
  end
39
42
 
40
43
  # Returns an array of ids for the given text.
@@ -65,7 +68,7 @@ module Picky
65
68
  # "exact title:Peter*:peter"
66
69
  #
67
70
  def to_s
68
- "#{category.bundle_for(token).identifier}(#{to_result.join(':')})"
71
+ "(#{category.bundle_for(token).identifier},#{to_result.join(':')})"
69
72
  end
70
73
 
71
74
  end
@@ -0,0 +1,59 @@
1
+ module Picky
2
+
3
+ module Query
4
+
5
+ class Combination
6
+
7
+ # Pretends to be a combination.
8
+ #
9
+ # TODO Rework completely and document.
10
+ #
11
+ class Or < Combination
12
+
13
+ def initialize combinations
14
+ @combinations = combinations
15
+ end
16
+
17
+ # Returns the combination's category name.
18
+ # Used in boosting.
19
+ #
20
+ def category_name
21
+ @category_name ||= @combinations.map(&:category_name).join('|').intern
22
+ end
23
+
24
+ # Returns the total (?) weight of its combinations.
25
+ #
26
+ # Note: Caching is most of the time useful.
27
+ #
28
+ def weight
29
+ @weight ||= @combinations.inject(0) do |sum, combination|
30
+ sum + combination.weight
31
+ end
32
+ end
33
+
34
+ # Returns an array of ids from its combinations.
35
+ #
36
+ # Note: Caching is most of the time useful.
37
+ #
38
+ def ids
39
+ @ids ||= @combinations.inject([]) do |total, combination|
40
+ total + combination.ids
41
+ end.uniq
42
+ end
43
+
44
+ def identifier
45
+ @identifier ||= "#{@combinations.map(&:bundle).map(&:identifier).join('|')}:inverted:#{token.text}"
46
+ end
47
+
48
+ def to_result
49
+ results = @combinations.map &:to_result
50
+ [*@combinations.map(&:to_result).transpose.map! { |thing| thing.join('|') }]
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
59
+ end
@@ -110,7 +110,7 @@ module Picky
110
110
  def allocation_for tokens, index
111
111
  # Expand the combinations.
112
112
  #
113
- possible_combinations = tokens.possible_combinations_in index
113
+ possible_combinations = tokens.possible_combinations_in index.categories
114
114
 
115
115
  # Generate all possible combinations.
116
116
  #
@@ -0,0 +1,47 @@
1
+ module Picky
2
+
3
+ module Query
4
+
5
+ class Tokens
6
+
7
+ # This is a combination of multiple (already processed) tokens, combined using
8
+ # the OR character, usually | (pipe).
9
+ #
10
+ # It pretends to be a single token and answers to all messages
11
+ # a token would answer to.
12
+ #
13
+ class Or < Tokens
14
+
15
+ def initialize processed_tokens
16
+ @tokens = processed_tokens
17
+ end
18
+
19
+ # TODO
20
+ #
21
+ def possible_combinations categories
22
+ combinations = @tokens.inject([]) do |result, token|
23
+ result + token.possible_combinations(categories)
24
+ end
25
+ combinations.empty? && combinations || [Query::Combination::Or.new(combinations)]
26
+ end
27
+
28
+ # # Returns the token in the form
29
+ # # ['original:Text', 'processedtext']
30
+ # #
31
+ # def to_result
32
+ # [originals.join('|'), texts.join('|')]
33
+ # end
34
+
35
+ # # Just join the token original texts.
36
+ # #
37
+ # def to_s
38
+ # "#{self.class}(#{originals.join '|'})"
39
+ # end
40
+
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -148,8 +148,8 @@ module Picky
148
148
  #
149
149
  @@no_similar_character = '"'
150
150
  @@similar_character = '~'
151
- @@no_similar = %r{#{@@no_similar_character}\z}
152
- @@similar = %r{#{@@similar_character}\z}
151
+ @@no_similar = %r{#@@no_similar_character\z}
152
+ @@similar = %r{#@@similar_character\z}
153
153
  def similarize
154
154
  self.similar = false or return unless @text !~ @@no_similar
155
155
  self.similar = true unless @text !~ @@similar
@@ -222,14 +222,25 @@ module Picky
222
222
  @text.gsub! @@illegals, EMPTY_STRING unless @text == EMPTY_STRING
223
223
  end
224
224
  def self.redefine_illegals
225
- @@illegals = %r{[#{@@no_similar_character}#{@@partial_character}#{@@similar_character}]}
225
+ @@illegals = %r{[#@@no_similar_character#@@partial_character#@@similar_character]}
226
226
  end
227
227
  redefine_illegals
228
-
229
- # Returns an array of possible combinations.
228
+
229
+ # Return all possible combinations.
230
+ #
231
+ # This checks if it needs to also search through similar
232
+ # tokens, if for example, the token is one with ~.
233
+ # If yes, it puts together all solutions.
234
+ #
235
+ def possible_combinations categories
236
+ similar? ? categories.similar_possible_for(self) : categories.possible_for(self)
237
+ end
238
+
239
+ # TODO
230
240
  #
231
- def possible_combinations_in index
232
- index.possible_combinations self
241
+ def combination_for category
242
+ weight = category.weight self
243
+ weight && Query::Combination.new(self, category, weight)
233
244
  end
234
245
 
235
246
  # Returns all similar tokens for the token.
@@ -310,7 +321,7 @@ module Picky
310
321
  # Note: Used in many backends.
311
322
  #
312
323
  def identifier
313
- "#{similar?? :similarity : :inverted}:#{@text}"
324
+ "#{similar?? :similarity : :inverted}:#@text"
314
325
  end
315
326
 
316
327
  # If the originals & the text are the same, they are the same.
@@ -13,6 +13,8 @@ module Picky
13
13
  # Basically forwards to its internal tokens array.
14
14
  #
15
15
  forward *[Enumerable.instance_methods, :slice!, :[], :uniq!, :last, :reject!, :length, :size, :empty?, :each, :exit, :to => :@tokens].flatten
16
+ each_forward :partial=,
17
+ :to => :@tokens
16
18
 
17
19
  # Create a new Tokens object with the array of tokens passed in.
18
20
  #
@@ -24,7 +26,14 @@ module Picky
24
26
  # Creates a new Tokens object from a number of Strings.
25
27
  #
26
28
  def self.processed words, originals, ignore_unassigned = false
27
- new words.zip(originals).collect! { |word, original| Token.processed word, original }, ignore_unassigned
29
+ new(words.zip(originals).collect! do |word, original|
30
+ w, *middle, rest = word.split(/\|/)
31
+ if rest
32
+ Or.new processed [w, *middle, rest], original.split(/\|/)
33
+ else
34
+ Token.processed w, original
35
+ end
36
+ end, ignore_unassigned)
28
37
  end
29
38
 
30
39
  # Generates an array in the form of
@@ -34,10 +43,10 @@ module Picky
34
43
  # [combination, combination] # of token 3
35
44
  # ]
36
45
  #
37
- def possible_combinations_in index
46
+ def possible_combinations_in categories
38
47
  @tokens.inject([]) do |combinations, token|
39
- possible_combinations = token.possible_combinations_in index
40
-
48
+ possible_combinations = token.possible_combinations categories
49
+
41
50
  # Note: Optimization for ignoring tokens that allocate to nothing and
42
51
  # can be ignored.
43
52
  # For example in a special search, where "florian" is not
@@ -63,11 +72,19 @@ module Picky
63
72
  @tokens.last.partial = true unless empty?
64
73
  end
65
74
 
66
- #
75
+ # TODO
67
76
  #
68
77
  def originals
69
78
  @tokens.map(&:original)
70
79
  end
80
+ def original
81
+ @tokens.map(&:original)
82
+ end
83
+ # TODO
84
+ #
85
+ def texts
86
+ @tokens.map(&:text)
87
+ end
71
88
 
72
89
  #
73
90
  #
data/lib/picky/search.rb CHANGED
@@ -275,7 +275,7 @@ module Picky
275
275
  s = "#{self.class}("
276
276
  ary = []
277
277
  ary << @indexes.indexes.map(&:name).join(', ') unless @indexes.indexes.empty?
278
- ary << "boosts: #{@boosts}" if @boosts
278
+ ary << "boosts: #@boosts" if @boosts
279
279
  s << ary.join(', ')
280
280
  s << ")"
281
281
  s
@@ -8,8 +8,6 @@ describe "Array IDs" do
8
8
  #
9
9
  it 'can use Arrays as IDs' do
10
10
  index = Picky::Index.new :arrays do
11
- key_format :to_a
12
-
13
11
  category :text1
14
12
  end
15
13
 
@@ -26,7 +24,7 @@ describe "Array IDs" do
26
24
  try.search("text1:ohai").ids.should == [
27
25
  ["id2", "thing2"],
28
26
  ["id1", "thing1"]
29
- ] # WAT
27
+ ]
30
28
  end
31
29
 
32
30
  # This tests the weights option.
@@ -51,7 +49,7 @@ describe "Array IDs" do
51
49
  try.search("text1:ohai").ids.should == [
52
50
  ["id2", "thing2"],
53
51
  ["id1", "thing1"]
54
- ] # WAT
52
+ ]
55
53
  end
56
54
 
57
55
  end
@@ -73,9 +73,9 @@ describe 'custom delimiters' do
73
73
  Picky::Query::Token.qualifier_text_delimiter = '?'
74
74
  try.search("text1?hello text2?world").ids.should == [1]
75
75
 
76
- try.search("text1|text2?hello text2?world").ids.should == []
77
- Picky::Query::Token.qualifiers_delimiter = '|'
78
- try.search("text1|text2?hello text2?world").ids.should == [1]
76
+ try.search("text1!text2?hello text2?world").ids.should == []
77
+ Picky::Query::Token.qualifiers_delimiter = '!'
78
+ try.search("text1!text2?hello text2?world").ids.should == [1]
79
79
  end
80
80
 
81
81
  it 'offers custom range characters to be set' do
@@ -54,6 +54,8 @@ describe "exact first" do
54
54
  require 'ostruct'
55
55
 
56
56
  data = Picky::Index.new :exact_first do
57
+ key_format :to_i
58
+
57
59
  source { [
58
60
  OpenStruct.new(id: 1, text: "discofox"),
59
61
  OpenStruct.new(id: 2, text: "disco")
@@ -0,0 +1,104 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+ require 'ostruct'
5
+
6
+ describe "OR token" do
7
+
8
+ it 'handles simple cases' do
9
+ index = Picky::Index.new :or do
10
+ category :text
11
+ end
12
+
13
+ thing = OpenStruct.new id: 1, text: "hello ohai"
14
+ other = OpenStruct.new id: 2, text: "hello kthxbye"
15
+
16
+ index.add thing
17
+ index.add other
18
+
19
+ try = Picky::Search.new index
20
+
21
+ # With or, or |.
22
+ #
23
+ try.search("hello text:ohai|text:kthxbye").ids.should == [1, 2]
24
+ try.search("hello text:ohai|kthxbye").ids.should == [1, 2]
25
+ try.search("hello ohai|text:kthxbye").ids.should == [1, 2]
26
+ try.search("hello ohai|kthxbye").ids.should == [1, 2]
27
+
28
+ # Still works.
29
+ #
30
+ try.search("hello text:ohai").ids.should == [1]
31
+ end
32
+
33
+ it 'handles more complex cases' do
34
+ index = Picky::Index.new :or do
35
+ category :text1
36
+ category :text2
37
+ end
38
+
39
+ thing = OpenStruct.new id: 1, text1: "hello world", text2: "ohai kthxbye"
40
+ other = OpenStruct.new id: 2, text1: "hello something else", text2: "to be or not to be"
41
+
42
+ index.add thing
43
+ index.add other
44
+
45
+ try = Picky::Search.new index
46
+
47
+ # With or, or |.
48
+ #
49
+ # Note that the order is changed.
50
+ #
51
+ try.search("hello ohai|not").ids.should == [1, 2]
52
+ try.search("hello not|ohai").ids.should == [2, 1]
53
+ try.search("hello ohai|kthxbye").ids.should == [1]
54
+ try.search("hello nonexisting|not").ids.should == [2]
55
+ try.search("hello nonexisting|alsononexisting").ids.should == []
56
+ try.search("hello text1:world|text2:not|text2:kthxbye").ids.should == [1, 2]
57
+ end
58
+
59
+ it 'handles even more complex cases' do
60
+ index = Picky::Index.new :or do
61
+ category :text, similarity: Picky::Similarity::DoubleMetaphone.new(3)
62
+ end
63
+
64
+ thing = OpenStruct.new id: 1, text: "hello ohai tester 13"
65
+ other = OpenStruct.new id: 2, text: "hello kthxbye"
66
+
67
+ index.add thing
68
+ index.add other
69
+
70
+ try = Picky::Search.new index
71
+
72
+ # With or, or |.
73
+ #
74
+ try.search("something,other:ohai").ids.should == []
75
+ try.search("text:taster~|text:kthxbye hello").ids.should == [2, 1]
76
+ try.search("text:test*|kthxbye hello").ids.should == [2, 1]
77
+ try.search("text:11-15|kthxbye hello").ids.should == [2, 1]
78
+ try.search("hello text,other:ohai|text:kthxbye").ids.should == [1, 2]
79
+ try.search("hello something,other:ohai|kthxbye").ids.should == [2]
80
+ try.search("hello text:oh*|text:kthxbya~").ids.should == [1, 2]
81
+ end
82
+
83
+ it 'handles multi-ORs' do
84
+ index = Picky::Index.new :or do
85
+ category :text, similarity: Picky::Similarity::DoubleMetaphone.new(3)
86
+ end
87
+
88
+ thing = OpenStruct.new id: 1, text: "that thing"
89
+ something = OpenStruct.new id: 2, text: "and something"
90
+ other = OpenStruct.new id: 3, text: "or other"
91
+
92
+ index.add thing
93
+ index.add something
94
+ index.add other
95
+
96
+ try = Picky::Search.new index
97
+
98
+ # With or, or |.
99
+ #
100
+ try.search("thing|something|other").ids.should == [1, 2, 3]
101
+ try.search("something|other").ids.should == [2, 3]
102
+ end
103
+
104
+ end
@@ -31,17 +31,19 @@ describe 'GC stats: searching' do
31
31
  # TODO Why are both versions almost equally fast?
32
32
  #
33
33
  context 'without pool' do
34
- it 'runs the GC more' do
35
- # Quickly check if the pool is removed.
36
- #
37
- fail 'object pool still installed' if Picky::Query::Token.respond_to? :release_all
38
-
39
- try = search
40
- query = 'abracadabra mirgel'
41
- gc_runs_of do
42
- amount.times { try.search query }
43
- end.should >= 10
44
- end
34
+ # TODO Reinstate after checking assumption about Ruby 2.
35
+ #
36
+ # it 'runs the GC more' do
37
+ # # Quickly check if the pool is removed.
38
+ # #
39
+ # fail 'object pool still installed' if Picky::Query::Token.respond_to? :release_all
40
+ #
41
+ # try = search
42
+ # query = 'abracadabra mirgel'
43
+ # gc_runs_of do
44
+ # amount.times { try.search query }
45
+ # end.should >= 10
46
+ # end
45
47
  it 'is less (?) performant' do
46
48
  try = search
47
49
  query = 'abracadabra mirgel'
@@ -12,6 +12,8 @@ describe "special sorting" do
12
12
 
13
13
  it 'returns exact results first' do
14
14
  data = Picky::Index.new :sorted do
15
+ key_format :to_i
16
+
15
17
  category :first, partial: Picky::Partial::Substring.new(from: 1)
16
18
  category :last, partial: Picky::Partial::Substring.new(from: 1)
17
19
  end
@@ -77,64 +77,64 @@ describe Picky::Categories do
77
77
  @categories << @category3
78
78
  end
79
79
 
80
- describe "possible_combinations" do
81
- before(:each) do
82
- @token = stub :token
83
- end
84
- context "with similar token" do
85
- before(:each) do
86
- @token.stub :similar? => true, :categorize => nil
87
- end
88
- it "calls the right method" do
89
- @categories.should_receive(:similar_possible_for).once.with @token
90
-
91
- @categories.possible_combinations @token
92
- end
93
- end
94
- context "with non-similar token" do
95
- before(:each) do
96
- @token.stub :similar? => false, :categorize => nil
97
- end
98
- it "calls the right method" do
99
- @categories.should_receive(:possible_for).once.with @token
100
-
101
- @categories.possible_combinations @token
102
- end
103
- end
104
- end
105
-
106
- describe 'possible_for' do
107
- context 'without preselected categories' do
108
- context 'user defined exists' do
109
- before(:each) do
110
- @token = stub :token, :predefined_categories => [@category2]
111
- end
112
- context 'combination exists' do
113
- before(:each) do
114
- @combination = stub :combination
115
- @category2.stub! :combination_for => @combination
116
- end
117
- it 'should return the right combinations' do
118
- @categories.possible_for(@token).should == [@combination]
119
- end
120
- end
121
- context 'combination does not exist' do
122
- before(:each) do
123
- @category2.stub! :combination_for => nil
124
- end
125
- it 'should return the right combinations' do
126
- @categories.possible_for(@token).should == []
127
- end
128
- end
129
- end
130
- context 'user defined does not exist' do
131
-
132
- end
133
- end
134
- context 'with preselected categories' do
135
-
136
- end
137
- end
80
+ # describe "possible_combinations" do
81
+ # before(:each) do
82
+ # @token = stub :token
83
+ # end
84
+ # context "with similar token" do
85
+ # before(:each) do
86
+ # @token.stub :similar? => true, :categorize => nil
87
+ # end
88
+ # it "calls the right method" do
89
+ # @categories.should_receive(:similar_possible_for).once.with @token
90
+ #
91
+ # @categories.possible_combinations @token
92
+ # end
93
+ # end
94
+ # context "with non-similar token" do
95
+ # before(:each) do
96
+ # @token.stub :similar? => false, :categorize => nil
97
+ # end
98
+ # it "calls the right method" do
99
+ # @categories.should_receive(:possible_for).once.with @token
100
+ #
101
+ # @categories.possible_combinations @token
102
+ # end
103
+ # end
104
+ # end
105
+
106
+ # describe 'possible_for' do
107
+ # context 'without preselected categories' do
108
+ # context 'user defined exists' do
109
+ # before(:each) do
110
+ # @token = Picky::Query::Token.processed 'hello'
111
+ # end
112
+ # context 'combination exists' do
113
+ # before(:each) do
114
+ # @combination = stub :combination
115
+ # @category2.stub! :combination_for => @combination
116
+ # end
117
+ # it 'should return the right combinations' do
118
+ # @categories.possible_for(@token).should == [@combination]
119
+ # end
120
+ # end
121
+ # context 'combination does not exist' do
122
+ # before(:each) do
123
+ # @category2.stub! :combination_for => nil
124
+ # end
125
+ # it 'should return the right combinations' do
126
+ # @categories.possible_for(@token).should == []
127
+ # end
128
+ # end
129
+ # end
130
+ # context 'user defined does not exist' do
131
+ #
132
+ # end
133
+ # end
134
+ # context 'with preselected categories' do
135
+ #
136
+ # end
137
+ # end
138
138
 
139
139
  describe 'possible_categories' do
140
140
  context 'user defined exists' do
@@ -182,30 +182,30 @@ describe Picky::Category do
182
182
  end
183
183
  end
184
184
 
185
- describe 'combination_for' do
186
- context 'no weight for token' do
187
- before(:each) do
188
- @category.stub! :weight => nil
189
- end
190
- it 'should return nil' do
191
- @category.combination_for(:anything).should == nil
192
- end
193
- end
194
- context 'weight for token' do
195
- before(:each) do
196
- @token = stub :token, :text => :some_text
197
- @category.stub! :weight => :some_weight, :bundle_for => :bundle
198
- end
199
- it 'should return a new combination' do
200
- @category.combination_for(@token).should be_kind_of(Picky::Query::Combination)
201
- end
202
- it 'should create the combination correctly' do
203
- Picky::Query::Combination.should_receive(:new).once.with @token, @category
204
-
205
- @category.combination_for @token
206
- end
207
- end
208
- end
185
+ # describe 'combination_for' do
186
+ # context 'no weight for token' do
187
+ # before(:each) do
188
+ # @category.stub! :weight => nil
189
+ # end
190
+ # it 'should return nil' do
191
+ # @category.combination_for(:anything).should == nil
192
+ # end
193
+ # end
194
+ # context 'weight for token' do
195
+ # before(:each) do
196
+ # @token = stub :token, :text => :some_text
197
+ # @category.stub! :weight => :some_weight, :bundle_for => :bundle
198
+ # end
199
+ # it 'should return a new combination' do
200
+ # @category.combination_for(@token).should be_kind_of(Picky::Query::Combination)
201
+ # end
202
+ # it 'should create the combination correctly' do
203
+ # Picky::Query::Combination.should_receive(:new).once.with @token, @category
204
+ #
205
+ # @category.combination_for @token
206
+ # end
207
+ # end
208
+ # end
209
209
 
210
210
  context 'stubbed exact/partial' do
211
211
  before(:each) do
@@ -59,11 +59,11 @@ describe Picky::Category do
59
59
  .and_yield(5, :some_token)
60
60
  category.stub! :prepared => prepared
61
61
 
62
- category.should_receive(:add_tokenized_token).once.with(1, :some_token, :<<)
63
- category.should_receive(:add_tokenized_token).once.with(2, :some_token, :<<)
64
- category.should_receive(:add_tokenized_token).once.with(3, :some_token, :<<)
65
- category.should_receive(:add_tokenized_token).once.with(4, :some_token, :<<)
66
- category.should_receive(:add_tokenized_token).once.with(5, :some_token, :<<)
62
+ category.should_receive(:add_tokenized_token).once.with(1, :some_token, :<<, nil)
63
+ category.should_receive(:add_tokenized_token).once.with(2, :some_token, :<<, nil)
64
+ category.should_receive(:add_tokenized_token).once.with(3, :some_token, :<<, nil)
65
+ category.should_receive(:add_tokenized_token).once.with(4, :some_token, :<<, nil)
66
+ category.should_receive(:add_tokenized_token).once.with(5, :some_token, :<<, nil)
67
67
 
68
68
  category.retrieve
69
69
  end
@@ -37,13 +37,6 @@ describe Picky::Index do
37
37
  @index.load
38
38
  end
39
39
  end
40
- describe "possible_combinations" do
41
- it "forwards to the combinator" do
42
- @categories.should_receive(:possible_combinations).once.with :some_token
43
-
44
- @index.possible_combinations :some_token
45
- end
46
- end
47
40
  end
48
41
 
49
42
  context 'result_identifier' do
@@ -12,41 +12,23 @@ describe Picky::Query::Combination do
12
12
  :name => :some_category_name,
13
13
  :identifier => 'some_category_identifier'
14
14
 
15
- @combination = described_class.new @token, @category
15
+ @combination = described_class.new @token, @category, 3.14
16
16
  end
17
17
 
18
18
  describe "to_s" do
19
19
  it "shows the combination's info" do
20
20
  @token.stub! :to_result => :token_result
21
21
 
22
- @combination.to_s.should == 'bundle_name(some_category_name:token_result)'
22
+ @combination.to_s.should == '(bundle_name,some_category_name:token_result)'
23
23
  end
24
24
  end
25
25
 
26
- # describe 'hash' do
27
- # it 'should hash the token and the bundle' do
28
- # @combination.hash.should == [@token, @category].hash
29
- # end
30
- # it 'should distinguish two combinations sufficiently' do
31
- # category1 = stub :category,
32
- # :identifier => 'some_category_identifier1'
33
- #
34
- # category2 = stub :category,
35
- # :identifier => 'some_category_identifier2'
36
- #
37
- # combination1 = described_class.new @token, category1
38
- # combination2 = described_class.new @token, category2
39
- #
40
- # combination1.hash.should_not == combination2.hash
41
- # end
42
- # end
43
-
44
26
  describe 'to_result' do
45
27
  context 'functional with qualifier' do
46
28
  before(:each) do
47
29
  token = Picky::Query::Token.processed 'name:blä~', 'Blä~'
48
30
 
49
- @combination = Picky::Query::Combination.new token, @category
31
+ @combination = Picky::Query::Combination.new token, @category, 3.14
50
32
  end
51
33
  it 'should return a correct result' do
52
34
  @combination.to_result.should == [:some_category_name, 'Blä~', 'blä'] # Note: Characters not substituted. That's ok.
@@ -82,18 +64,8 @@ describe Picky::Query::Combination do
82
64
  end
83
65
 
84
66
  describe 'weight' do
85
- it 'should call weight with the text on bundle' do
86
- @category.should_receive(:weight).once.with @token
87
-
88
- @combination.weight
89
- end
90
- it 'should not call it twice, but cache' do
91
- @category.stub! :weight => :some_weight
92
- @combination.weight
93
-
94
- @category.should_receive(:weight).never
95
-
96
- @combination.weight.should == :some_weight
67
+ it 'should return the weight' do
68
+ @combination.weight.should == 3.14
97
69
  end
98
70
  end
99
71
 
@@ -26,9 +26,9 @@ describe Picky::Query::Tokens do
26
26
  @tokens = described_class.new [@token1, @token2, @token3], true
27
27
  end
28
28
  it 'should work correctly' do
29
- @token1.should_receive(:possible_combinations_in).once.with(:some_index).and_return [:combination11, :combination12]
30
- @token2.should_receive(:possible_combinations_in).once.with(:some_index).and_return [:combination21]
31
- @token3.should_receive(:possible_combinations_in).once.with(:some_index).and_return [:combination31, :combination32, :combination33]
29
+ @token1.should_receive(:possible_combinations).once.with(:some_index).and_return [:combination11, :combination12]
30
+ @token2.should_receive(:possible_combinations).once.with(:some_index).and_return [:combination21]
31
+ @token3.should_receive(:possible_combinations).once.with(:some_index).and_return [:combination31, :combination32, :combination33]
32
32
 
33
33
  @tokens.possible_combinations_in(:some_index).should == [
34
34
  [:combination11, :combination12],
@@ -37,9 +37,9 @@ describe Picky::Query::Tokens do
37
37
  ]
38
38
  end
39
39
  it 'should work correctly' do
40
- @token1.should_receive(:possible_combinations_in).once.with(:some_index).and_return [:combination11, :combination12]
41
- @token2.should_receive(:possible_combinations_in).once.with(:some_index).and_return []
42
- @token3.should_receive(:possible_combinations_in).once.with(:some_index).and_return [:combination31, :combination32, :combination33]
40
+ @token1.should_receive(:possible_combinations).once.with(:some_index).and_return [:combination11, :combination12]
41
+ @token2.should_receive(:possible_combinations).once.with(:some_index).and_return []
42
+ @token3.should_receive(:possible_combinations).once.with(:some_index).and_return [:combination31, :combination32, :combination33]
43
43
 
44
44
  @tokens.possible_combinations_in(:some_index).should == [
45
45
  [:combination11, :combination12],
@@ -171,9 +171,9 @@ describe Picky::Query::Tokens do
171
171
  @tokens = described_class.new [@token1, @token2, @token3]
172
172
  end
173
173
  it 'should work correctly' do
174
- @token1.should_receive(:possible_combinations_in).once.with(:some_index).and_return [:combination11, :combination12]
175
- @token2.should_receive(:possible_combinations_in).once.with(:some_index).and_return [:combination21]
176
- @token3.should_receive(:possible_combinations_in).once.with(:some_index).and_return [:combination31, :combination32, :combination33]
174
+ @token1.should_receive(:possible_combinations).once.with(:some_index).and_return [:combination11, :combination12]
175
+ @token2.should_receive(:possible_combinations).once.with(:some_index).and_return [:combination21]
176
+ @token3.should_receive(:possible_combinations).once.with(:some_index).and_return [:combination31, :combination32, :combination33]
177
177
 
178
178
  @tokens.possible_combinations_in(:some_index).should == [
179
179
  [:combination11, :combination12],
@@ -182,9 +182,9 @@ describe Picky::Query::Tokens do
182
182
  ]
183
183
  end
184
184
  it 'should work correctly' do
185
- @token1.should_receive(:possible_combinations_in).once.with(:some_index).and_return [:combination11, :combination12]
186
- @token2.should_receive(:possible_combinations_in).once.with(:some_index).and_return nil
187
- @token3.should_receive(:possible_combinations_in).once.with(:some_index).and_return [:combination31, :combination32, :combination33]
185
+ @token1.should_receive(:possible_combinations).once.with(:some_index).and_return [:combination11, :combination12]
186
+ @token2.should_receive(:possible_combinations).once.with(:some_index).and_return nil
187
+ @token3.should_receive(:possible_combinations).once.with(:some_index).and_return [:combination31, :combination32, :combination33]
188
188
 
189
189
  @tokens.possible_combinations_in(:some_index).should == [
190
190
  [:combination11, :combination12],
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: picky
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.16.0
4
+ version: 4.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Hanke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-12 00:00:00.000000000 Z
11
+ date: 2013-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ~>
46
46
  - !ruby/object:Gem::Version
47
- version: 4.16.0
47
+ version: 4.17.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
- version: 4.16.0
54
+ version: 4.17.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: text
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -226,10 +226,12 @@ files:
226
226
  - lib/picky/query/allocation.rb
227
227
  - lib/picky/query/allocations.rb
228
228
  - lib/picky/query/boosts.rb
229
+ - lib/picky/query/combination/or.rb
229
230
  - lib/picky/query/combination.rb
230
231
  - lib/picky/query/combinations.rb
231
232
  - lib/picky/query/indexes/check.rb
232
233
  - lib/picky/query/indexes.rb
234
+ - lib/picky/query/or.rb
233
235
  - lib/picky/query/token.rb
234
236
  - lib/picky/query/tokens.rb
235
237
  - lib/picky/rack/harakiri.rb
@@ -288,6 +290,7 @@ files:
288
290
  - spec/functional/no_tokenize_spec.rb
289
291
  - spec/functional/non_specific_ids_larger_than_20_spec.rb
290
292
  - spec/functional/only_spec.rb
293
+ - spec/functional/or_spec.rb
291
294
  - spec/functional/pool_spec.rb
292
295
  - spec/functional/range_queries_spec.rb
293
296
  - spec/functional/realtime_spec.rb
@@ -411,7 +414,9 @@ files:
411
414
  YmluL3BpY2t5
412
415
  - ext/picky/extconf.rb
413
416
  homepage: http://florianhanke.com/picky
414
- licenses: []
417
+ licenses:
418
+ - MIT
419
+ - LGPL
415
420
  metadata: {}
416
421
  post_install_message:
417
422
  rdoc_options: []
@@ -460,6 +465,7 @@ test_files:
460
465
  - spec/functional/no_tokenize_spec.rb
461
466
  - spec/functional/non_specific_ids_larger_than_20_spec.rb
462
467
  - spec/functional/only_spec.rb
468
+ - spec/functional/or_spec.rb
463
469
  - spec/functional/pool_spec.rb
464
470
  - spec/functional/range_queries_spec.rb
465
471
  - spec/functional/realtime_spec.rb