picky 4.15.0 → 4.15.1

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 ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ M2MxMTQxZjI1MDcwYzA1N2UzNWY2MTQ5ZGNkMTllYWFjYmI1MDk0Nw==
5
+ data.tar.gz: !binary |-
6
+ NjA3MTc5MTEwMWUzZWQ1NGZjNWU0ZjRhZDJmMTJhZjhhYjdiZWIzNA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NjdhYmYyYTkwOGJlZmUzZjljYTA2MjIxNzg0NWEwYzZkZWE2ZmE3OTdmZGEz
10
+ Mjc4YjYwMWZlMTU4Zjk0NGQyNGE4NzM2MjA0ZWY2MGRkODlhM2Y5Y2ZhYWZk
11
+ MzFjOWM2ZTQ4MzQzYTFiYTA3ZjUyZmQyZTU1NGU0ZjExMGQyYTA=
12
+ data.tar.gz: !binary |-
13
+ MzlhODU0NmZlNGRkOGM4YzlkZDY3MTQxYmJlYTA2MWJkYWEwMGI4MjEwNzA1
14
+ M2VhYjExNzQ2YzdhODcyZjE0ZWVlN2QzMDRmNTU0YTI0YjVjMjFkNzc1ODk2
15
+ ZjQ3OTQyNTVhNmY3ZjhiN2ZhZWY4MWM0OTcyMDYxYjIzMTQ1YTY=
@@ -1,6 +1,17 @@
1
1
  # encoding: utf-8
2
2
  #
3
3
 
4
+ class Range
5
+ def expand_with thing
6
+ return (thing..thing) unless min
7
+ if max < thing
8
+ (min..thing)
9
+ else
10
+ thing < min ? (thing..max) : self
11
+ end
12
+ end
13
+ end
14
+
4
15
  # Analyzes indexes (index bundles, actually).
5
16
  #
6
17
  class Analyzer
@@ -38,46 +49,39 @@ class Analyzer
38
49
 
39
50
  self
40
51
  end
52
+
41
53
  def cardinality identifier, index
42
- return if index.size.zero?
43
- return unless index.respond_to?(:each_pair)
44
-
45
- key_length_average = 0
46
- ids_length_average = 0
54
+ return unless can_calculate_cardinality? index
47
55
 
48
- min_ids_length = 1.0/0 # Infinity
49
- max_ids_length = 0
50
- min_key_length = 1.0/0 # Infinity
51
- max_key_length = 0
56
+ key_length_sum = 0
57
+ ids_length_sum = 0
58
+
59
+ key_length = (1.0/0..0)
60
+ ids_length = (1.0/0..0)
52
61
 
53
- key_size, ids_size = 0, 0
54
62
  index.each_pair do |key, ids|
55
- key_size = key.size
56
- if key_size < min_key_length
57
- min_key_length = key_size
58
- else
59
- max_key_length = key_size if key_size > max_key_length
60
- end
61
- key_length_average += key_size
62
-
63
- ids_size = ids.size
64
- if ids_size < min_ids_length
65
- min_ids_length = ids_size
66
- else
67
- max_ids_length = ids_size if ids_size > max_ids_length
68
- end
69
- ids_length_average += ids_size
63
+ key_length = key_length.expand_with key.size
64
+ key_length_sum += key.size
65
+ ids_length = ids_length.expand_with ids.size
66
+ ids_length_sum += ids.size
70
67
  end
71
- index_size = index.size
72
- key_length_average = key_length_average.to_f / index_size
73
- ids_length_average = ids_length_average.to_f / index_size
74
-
75
- analysis[identifier] ||= {}
76
- analysis[identifier][:key_length] = (min_key_length..max_key_length)
77
- analysis[identifier][:ids_length] = (min_ids_length..max_ids_length)
78
- analysis[identifier][:key_length_average] = key_length_average
79
- analysis[identifier][:ids_length_average] = ids_length_average
68
+
69
+ report_cardinality identifier, index, key_length, ids_length, key_length_sum, ids_length_sum
70
+ end
71
+ def report_cardinality identifier, index, key_length, ids_length, key_length_sum, ids_length_sum
72
+ analysis_identifier = analysis[identifier] ||= {}
73
+ analysis_identifier[:key_length] = key_length
74
+ analysis_identifier[:ids_length] = ids_length
75
+ analysis_identifier[:key_length_average] = key_length_sum.to_f / index.size
76
+ analysis_identifier[:ids_length_average] = ids_length_sum.to_f / index.size
77
+ end
78
+
79
+ def can_calculate_cardinality? index
80
+ return if index.size.zero?
81
+ return unless index.respond_to? :each_pair
82
+ true
80
83
  end
84
+
81
85
  def index_analysis
82
86
  return unless analysis[:index]
83
87
 
@@ -91,6 +95,7 @@ class Analyzer
91
95
  comments << "\033[33mIndex matches single characters.\033[m"
92
96
  end
93
97
  end
98
+
94
99
  def weights index
95
100
  return if !index.respond_to?(:size) || index.size.zero?
96
101
  return unless index.respond_to?(:each_pair)
@@ -115,6 +120,7 @@ class Analyzer
115
120
  analysis[:weights][:weight_range] = (min_weight..max_weight)
116
121
  analysis[:weights][:weight_average] = weight_average
117
122
  end
123
+
118
124
  def weights_analysis
119
125
  return unless analysis[:weights]
120
126
 
@@ -131,25 +137,36 @@ class Analyzer
131
137
  def to_s
132
138
  [*comments, index_to_s, weights_to_s, similarity_to_s, configuration_to_s].compact.join "\n"
133
139
  end
140
+
134
141
  def index_to_s
135
142
  return if analysis[:__keys].zero?
136
- ary = ["index key cardinality: #{"%10d" % analysis[:__keys]}"]
143
+ ary = ["index key cardinality: #{"%9d" % analysis[:__keys]}"]
137
144
  return ary.join "\n" unless analysis[:index]
138
- ary << formatted('', :key_length)
145
+ ary << formatted(nil, :key_length)
139
146
  ary << formatted('ids per', :ids_length)
140
147
  ary.join "\n"
141
148
  end
149
+
142
150
  def formatted description, key, index = :index
143
- "index #{description} key length range (avg): #{"%10s" % analysis[index][key]} (#{analysis[index][:"#{key}_average"].round(2)})"
151
+ what = "%-40s" % ["index", description, "key length range (avg):"].compact.join(' ')
152
+ range = "%7s" % analysis[index][key]
153
+ average = "%8s" % "(#{analysis[index][:"#{key}_average"].round(2)})"
154
+ what + range + average
144
155
  end
156
+
145
157
  def weights_to_s
146
158
  return unless analysis[:weights]
147
- %Q{weights range (avg): #{"%10s" % analysis[:weights][:weight_range]} (#{analysis[:weights][:weight_average].round(2)})}
159
+ what = "%-30s" % "weights range (avg):"
160
+ range = "%17s" % analysis[:weights][:weight_range]
161
+ average = "%8s" % "(#{analysis[:weights][:weight_average].round(2)})"
162
+ what + range + average
148
163
  end
164
+
149
165
  def similarity_to_s
150
166
  return unless analysis[:similarity]
151
167
  formatted('similarity', :key_length, :similarity)
152
168
  end
169
+
153
170
  def configuration_to_s
154
171
  # analysis[:configuration]
155
172
  end
@@ -17,7 +17,11 @@ module Picky
17
17
  # given object.
18
18
  #
19
19
  def add object, where = :unshift
20
- add_text object.id, object.send(from), where
20
+ if from.respond_to? :call
21
+ add_text object.id, from.call(object), where
22
+ else
23
+ add_text object.id, object.send(from), where
24
+ end
21
25
  end
22
26
 
23
27
  # Removes the object's id, and then
@@ -65,8 +69,13 @@ module Picky
65
69
  else
66
70
  tokens = text_or_tokens
67
71
  end
72
+
73
+ # TODO Have an "as is" key_format?
74
+ #
68
75
  tokens.each { |text| add_tokenized_token id.send(key_format), text, where, false }
69
76
  rescue NoMethodError
77
+ # TODO This also is raised on a wrong key_format.
78
+ # TODO Improve error message by pointing out what exactly goes wrong: thing xy does not have an #each method.
70
79
  raise %Q{You probably set tokenize: false on category "#{name}". It will need an Enumerator of previously tokenized tokens.}
71
80
  end
72
81
 
@@ -98,4 +107,4 @@ module Picky
98
107
 
99
108
  end
100
109
 
101
- end
110
+ end
@@ -5,7 +5,9 @@ module Picky
5
5
  class Index
6
6
  include Helpers::Indexing
7
7
 
8
- forward :cache, :clear, :to => :categories
8
+ forward :cache,
9
+ :clear,
10
+ :to => :categories
9
11
 
10
12
  # Define an index tokenizer on the index.
11
13
  #
@@ -21,6 +23,8 @@ module Picky
21
23
  # Decides whether to use a parallel indexer or whether to
22
24
  # forward to each category to prepare themselves.
23
25
  #
26
+ # TODO Do a critical reading of this on the blog.
27
+ #
24
28
  def prepare scheduler = Scheduler.new
25
29
  if source.respond_to?(:each)
26
30
  check_source_empty
@@ -79,7 +83,7 @@ module Picky
79
83
  some_source ? (@source = Source.from(some_source, false, name)) : unblock_source
80
84
  end
81
85
  # Get the actual source if it is wrapped in a time
82
- # capsule, i.e. a block/lambda.
86
+ # capsule, ie. a block/lambda.
83
87
  #
84
88
  def unblock_source
85
89
  @source.respond_to?(:call) ? @source.call : @source
@@ -87,7 +91,9 @@ module Picky
87
91
 
88
92
  # Define a key_format on the index.
89
93
  #
90
- # Parameter is a method name to use on the key (e.g. :to_i, :to_s, :strip).
94
+ # Parameter is a method name to use on the key (e.g. :to_i, :to_s, :strip, :split).
95
+ #
96
+ # TODO Rename id_format?
91
97
  #
92
98
  def key_format key_format = nil
93
99
  key_format ? (@key_format = key_format) : @key_format
@@ -0,0 +1,57 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ describe "Array IDs" do
6
+
7
+ # This tests the weights option.
8
+ #
9
+ it 'can use Arrays as IDs' do
10
+ index = Picky::Index.new :arrays do
11
+ key_format :to_a
12
+
13
+ category :text1
14
+ end
15
+
16
+ require 'ostruct'
17
+
18
+ thing = OpenStruct.new id: ['id1', 'thing1'], text1: "ohai"
19
+ other = OpenStruct.new id: ['id2', 'thing2'], text1: "ohai kthxbye"
20
+
21
+ index.add thing
22
+ index.add other
23
+
24
+ try = Picky::Search.new index
25
+
26
+ try.search("text1:ohai").ids.should == [
27
+ ["id2", "thing2"],
28
+ ["id1", "thing1"]
29
+ ] # WAT
30
+ end
31
+
32
+ # This tests the weights option.
33
+ #
34
+ it 'can use split as key_format' do
35
+ index = Picky::Index.new :arrays do
36
+ key_format :split
37
+
38
+ category :text1
39
+ end
40
+
41
+ require 'ostruct'
42
+
43
+ thing = OpenStruct.new id: "id1 thing1", text1: "ohai"
44
+ other = OpenStruct.new id: "id2 thing2", text1: "ohai kthxbye"
45
+
46
+ index.add thing
47
+ index.add other
48
+
49
+ try = Picky::Search.new index
50
+
51
+ try.search("text1:ohai").ids.should == [
52
+ ["id2", "thing2"],
53
+ ["id1", "thing1"]
54
+ ] # WAT
55
+ end
56
+
57
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+
5
+ describe "From option" do
6
+
7
+ it 'can be given a lambda' do
8
+ index = Picky::Index.new :lambda do
9
+ category :text, from: ->(thing){ thing.some_text * 2 } # Anything, really.
10
+ end
11
+
12
+ require 'ostruct'
13
+
14
+ thing = OpenStruct.new id: 1, some_text: "ohai"
15
+ other = OpenStruct.new id: 2, some_text: "ohai kthxbye"
16
+
17
+ index.add thing
18
+ index.add other
19
+
20
+ try = Picky::Search.new index
21
+
22
+ try.search("text:ohaiohai").ids.should == [1]
23
+ end
24
+
25
+ end
metadata CHANGED
@@ -1,93 +1,113 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: picky
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.15.0
5
- prerelease:
4
+ version: 4.15.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Florian Hanke
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-05-02 00:00:00.000000000 Z
11
+ date: 2013-06-13 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rspec
16
- requirement: &70116179207700 !ruby/object:Gem::Requirement
17
- none: false
15
+ requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
17
  - - ! '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
- version_requirements: *70116179207700
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
25
27
  - !ruby/object:Gem::Dependency
26
28
  name: rake-compiler
27
- requirement: &70116179229800 !ruby/object:Gem::Requirement
28
- none: false
29
+ requirement: !ruby/object:Gem::Requirement
29
30
  requirements:
30
31
  - - ! '>='
31
32
  - !ruby/object:Gem::Version
32
33
  version: '0'
33
34
  type: :development
34
35
  prerelease: false
35
- version_requirements: *70116179229800
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
36
41
  - !ruby/object:Gem::Dependency
37
42
  name: picky-client
38
- requirement: &70116179229120 !ruby/object:Gem::Requirement
39
- none: false
43
+ requirement: !ruby/object:Gem::Requirement
40
44
  requirements:
41
45
  - - ~>
42
46
  - !ruby/object:Gem::Version
43
- version: 4.15.0
47
+ version: 4.15.1
44
48
  type: :development
45
49
  prerelease: false
46
- version_requirements: *70116179229120
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 4.15.1
47
55
  - !ruby/object:Gem::Dependency
48
56
  name: text
49
- requirement: &70116179228440 !ruby/object:Gem::Requirement
50
- none: false
57
+ requirement: !ruby/object:Gem::Requirement
51
58
  requirements:
52
59
  - - ! '>='
53
60
  - !ruby/object:Gem::Version
54
61
  version: '0'
55
62
  type: :runtime
56
63
  prerelease: false
57
- version_requirements: *70116179228440
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: multi_json
60
- requirement: &70116179227980 !ruby/object:Gem::Requirement
61
- none: false
71
+ requirement: !ruby/object:Gem::Requirement
62
72
  requirements:
63
73
  - - ! '>='
64
74
  - !ruby/object:Gem::Version
65
75
  version: '0'
66
76
  type: :runtime
67
77
  prerelease: false
68
- version_requirements: *70116179227980
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: activesupport
71
- requirement: &70116179227480 !ruby/object:Gem::Requirement
72
- none: false
85
+ requirement: !ruby/object:Gem::Requirement
73
86
  requirements:
74
87
  - - ! '>='
75
88
  - !ruby/object:Gem::Version
76
89
  version: '3.0'
77
90
  type: :runtime
78
91
  prerelease: false
79
- version_requirements: *70116179227480
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
80
97
  - !ruby/object:Gem::Dependency
81
98
  name: rack_fast_escape
82
- requirement: &70116179227040 !ruby/object:Gem::Requirement
83
- none: false
99
+ requirement: !ruby/object:Gem::Requirement
84
100
  requirements:
85
101
  - - ! '>='
86
102
  - !ruby/object:Gem::Version
87
103
  version: '0'
88
104
  type: :runtime
89
105
  prerelease: false
90
- version_requirements: *70116179227040
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
91
111
  description: Fast Ruby semantic text search engine with comfortable single field interface.
92
112
  email: florian.hanke+picky@gmail.com
93
113
  executables:
@@ -244,6 +264,7 @@ files:
244
264
  - ext/picky/picky.c
245
265
  - spec/aux/picky/cli_spec.rb
246
266
  - spec/functional/allocations_uniq_by_definition_spec.rb
267
+ - spec/functional/arrays_as_ids_spec.rb
247
268
  - spec/functional/automatic_segmentation_spec.rb
248
269
  - spec/functional/backends/file_spec.rb
249
270
  - spec/functional/backends/memory_bundle_realtime_spec.rb
@@ -259,6 +280,7 @@ files:
259
280
  - spec/functional/error_messages_spec.rb
260
281
  - spec/functional/exact_first_spec.rb
261
282
  - spec/functional/facets_spec.rb
283
+ - spec/functional/from_spec.rb
262
284
  - spec/functional/ignore_allocations_spec.rb
263
285
  - spec/functional/ignore_spec.rb
264
286
  - spec/functional/max_allocations_spec.rb
@@ -385,35 +407,36 @@ files:
385
407
  - spec/lib/tasks/try_spec.rb
386
408
  - spec/lib/tokenizer_spec.rb
387
409
  - spec/performant_spec.rb
388
- - bin/picky
410
+ - !binary |-
411
+ YmluL3BpY2t5
389
412
  - ext/picky/extconf.rb
390
413
  homepage: http://florianhanke.com/picky
391
414
  licenses: []
415
+ metadata: {}
392
416
  post_install_message:
393
417
  rdoc_options: []
394
418
  require_paths:
395
419
  - lib
396
420
  required_ruby_version: !ruby/object:Gem::Requirement
397
- none: false
398
421
  requirements:
399
422
  - - ! '>='
400
423
  - !ruby/object:Gem::Version
401
424
  version: '0'
402
425
  required_rubygems_version: !ruby/object:Gem::Requirement
403
- none: false
404
426
  requirements:
405
427
  - - ! '>='
406
428
  - !ruby/object:Gem::Version
407
429
  version: '0'
408
430
  requirements: []
409
431
  rubyforge_project: http://rubyforge.org/projects/picky
410
- rubygems_version: 1.8.10
432
+ rubygems_version: 2.0.3
411
433
  signing_key:
412
- specification_version: 3
434
+ specification_version: 4
413
435
  summary: ! 'Picky: Semantic Search Engine. Clever Interface. Good Tools.'
414
436
  test_files:
415
437
  - spec/aux/picky/cli_spec.rb
416
438
  - spec/functional/allocations_uniq_by_definition_spec.rb
439
+ - spec/functional/arrays_as_ids_spec.rb
417
440
  - spec/functional/automatic_segmentation_spec.rb
418
441
  - spec/functional/backends/file_spec.rb
419
442
  - spec/functional/backends/memory_bundle_realtime_spec.rb
@@ -429,6 +452,7 @@ test_files:
429
452
  - spec/functional/error_messages_spec.rb
430
453
  - spec/functional/exact_first_spec.rb
431
454
  - spec/functional/facets_spec.rb
455
+ - spec/functional/from_spec.rb
432
456
  - spec/functional/ignore_allocations_spec.rb
433
457
  - spec/functional/ignore_spec.rb
434
458
  - spec/functional/max_allocations_spec.rb