picky 4.16.0 → 4.17.0

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