picky 4.26.2 → 4.27.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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c3a6133019bb7fb372e2ef9a8261ee69df1e562b
4
- data.tar.gz: 8dfb39edf77042b40276bc0e26d34286c3e71b79
3
+ metadata.gz: 20377f0b4ac92cd75659306842de34204b7bf85d
4
+ data.tar.gz: 7c3e252193f4be20dd6fb5013b11a9d427662051
5
5
  SHA512:
6
- metadata.gz: d21d378abbbd2ea37ca0eb6ce1e948c5904db3daa6f6df41797a6acaff996e12fcf43cf5c5cc536694d0883c5918ca6a1049fe22eed369ba563f495688999cef
7
- data.tar.gz: 50ca4ff1812761a21af2c5aaa781f75bddfd4fbe20a8de72334f660a826eba3c551933c56924e2415af7eebd240ce33aea588207700cc38c1a2ea27db04e5573
6
+ metadata.gz: 02e007ee3b0e7be2a4ce3c337bde4d496c4ccce05450196d8e7135d69d08dec5020d4fa8858b58ae54e170b64fd62677bd08df6c7eb348ada0c78252b7effbd2
7
+ data.tar.gz: 41285d5f985a0ed59407ba0b8f52526f122a86af8be4f90341b39d79884a2b922d9883a16ae39f0f6ecb997fb5edd1e5208c960d8811dedd09b1c22821c3bb8f
@@ -12,37 +12,23 @@ module Picky
12
12
 
13
13
  # Returns an object that on #initial, #load returns
14
14
  # an object that responds to:
15
- # [:token] # => [id, id, id, id, id] (an array of ids)
15
+ # object[:token] # => [id, id, id, id, id] (an array of ids)
16
16
  #
17
- def create_inverted bundle
17
+ def create_inverted bundle, _ = nil
18
18
  json bundle.index_path(:inverted)
19
19
  end
20
20
  # Returns an object that on #initial, #load returns
21
21
  # an object that responds to:
22
- # [:token] # => 1.23 (a weight)
22
+ # object[:key] # => value (a value for this config key)
23
23
  #
24
- # def create_weights bundle
25
- # json bundle.index_path(:weights)
26
- # end
27
- # # Returns an object that on #initial, #load returns
28
- # # an object that responds to:
29
- # # [:encoded] # => [:original, :original] (an array of original symbols this similarity encoded thing maps to)
30
- # #
31
- # def create_similarity bundle
32
- # Marshal.new bundle.index_path(:similarity)
33
- # end
34
- # Returns an object that on #initial, #load returns
35
- # an object that responds to:
36
- # [:key] # => value (a value for this config key)
37
- #
38
- def create_configuration bundle
24
+ def create_configuration bundle, _ = nil
39
25
  json bundle.index_path(:configuration)
40
26
  end
41
27
  # Returns an object that on #initial, #load returns
42
28
  # an object that responds to:
43
- # [id] # => [:sym1, :sym2]
29
+ # object[id] # => [:sym1, :sym2]
44
30
  #
45
- def create_realtime bundle
31
+ def create_realtime bundle, _ = nil
46
32
  json bundle.index_path(:realtime)
47
33
  end
48
34
 
@@ -10,11 +10,11 @@ module Picky
10
10
  #
11
11
  class File < Backend
12
12
 
13
- def create_weights bundle
13
+ def create_weights bundle, _ = nil
14
14
  Memory::JSON.new bundle.index_path(:weights)
15
15
  end
16
16
 
17
- def create_similarity bundle
17
+ def create_similarity bundle, _ = nil
18
18
  json bundle.index_path(:similarity)
19
19
  end
20
20
 
@@ -0,0 +1,46 @@
1
+ if require 'google_hash'
2
+
3
+ class ::GoogleHashSparseRubyToRuby
4
+
5
+ # This is mainly used in tests, which is
6
+ # why we allow for a silly implementation.
7
+ #
8
+ def == hash
9
+ return false unless hash.respond_to?(:to_h)
10
+
11
+ self.each do |key, value|
12
+ return false if hash[key] != value
13
+ end
14
+ hash.each do |key, value|
15
+ return false if self[key] != value
16
+ end
17
+
18
+ true
19
+ end
20
+
21
+ # I am a hashy thing.
22
+ #
23
+ def to_hash
24
+ true
25
+ end
26
+
27
+ #
28
+ #
29
+ def inject init, &block
30
+ result = init
31
+ each do |key, value|
32
+ result = block.call result, [key, value]
33
+ end
34
+ result
35
+ end
36
+
37
+ def size
38
+ result = 0
39
+ # each only accepts a block
40
+ each { result += 1 }
41
+ result
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -18,12 +18,17 @@ module Picky
18
18
  # This file's location.
19
19
  #
20
20
  attr_reader :cache_path
21
+
22
+ # What hash type to use. Default: ::Hash
23
+ #
24
+ attr_reader :hash_type
21
25
 
22
26
  # An index cache takes a path, without file extension,
23
27
  # which will be provided by the subclasses.
24
28
  #
25
- def initialize cache_path, options = {}
29
+ def initialize cache_path, hash_type = Hash, options = {}
26
30
  @cache_path = "#{cache_path}.memory.#{extension}"
31
+ @hash_type = hash_type
27
32
  @empty = options[:empty]
28
33
  @initial = options[:initial]
29
34
  end
@@ -38,7 +43,7 @@ module Picky
38
43
  # together before it is dumped into the files.
39
44
  #
40
45
  def empty
41
- @empty && @empty.clone || empty_hash
46
+ @empty && @empty.clone || hash_type.new
42
47
  end
43
48
 
44
49
  def empty_hash
@@ -50,10 +55,10 @@ module Picky
50
55
  end
51
56
  end
52
57
 
53
- # The initial content before loading from file.
58
+ # The initial content before loading from file/indexing.
54
59
  #
55
60
  def initial
56
- @initial && @initial.clone || {}
61
+ @initial && @initial.clone || hash_type.new
57
62
  end
58
63
 
59
64
  # Deletes the file.
@@ -4,13 +4,58 @@ module Picky
4
4
 
5
5
  class Memory < Backend
6
6
 
7
- def create_weights bundle
8
- JSON.new bundle.index_path(:weights)
7
+ # TODO Make lazy.
8
+ require_relative 'google_hash'
9
+
10
+ # Returns an object that on #initial, #load returns
11
+ # an object that responds to:
12
+ # object[:token] # => [id, id, id, id, id] (an array of ids)
13
+ #
14
+ def create_inverted bundle, hints = nil
15
+ json bundle.index_path(:inverted), hash_for(hints)
16
+ end
17
+
18
+ # Returns an object that on #initial, #load returns
19
+ # an object that responds to:
20
+ # object[:token] # => 1.23 (a weight)
21
+ #
22
+ def create_weights bundle, hints = nil
23
+ JSON.new bundle.index_path(:weights), hash_for(hints) # GoogleHashSparseRubyToInt (I wish they had floats)
24
+ end
25
+
26
+ # Returns an object that on #initial, #load returns
27
+ # an object that responds to:
28
+ # object[:encoded] # => [:original, :original] (an array of original symbols this similarity encoded thing maps to)
29
+ #
30
+ def create_similarity bundle, hints = nil
31
+ Marshal.new bundle.index_path(:similarity), hash_for(hints)
9
32
  end
10
33
 
11
- def create_similarity bundle
12
- Marshal.new bundle.index_path(:similarity)
34
+ # Returns an object that on #initial, #load returns
35
+ # an object that responds to:
36
+ # object[:key] # => value (a value for this config key)
37
+ #
38
+ def create_configuration bundle, hints = nil
39
+ json bundle.index_path(:configuration), hash_for(hints)
13
40
  end
41
+
42
+ # Returns an object that on #initial, #load returns
43
+ # an object that responds to:
44
+ # object[id] # => [:sym1, :sym2]
45
+ #
46
+ def create_realtime bundle, hints = nil
47
+ json bundle.index_path(:realtime), hash_for(hints) # GoogleHashSparseLongToRuby # FIXME This is only true on number keys (add Picky hints).
48
+ end
49
+
50
+ private
51
+
52
+ def hash_for hints
53
+ if hints && hints.does?(:no_dump)
54
+ ::GoogleHashSparseRubyToRuby
55
+ else
56
+ ::Hash
57
+ end
58
+ end
14
59
 
15
60
  end
16
61
 
@@ -36,31 +36,31 @@ module Picky
36
36
  # Returns an object that on #initial, #load returns an object that responds to:
37
37
  # [:token] # => [id, id, id, id, id] (an array of ids)
38
38
  #
39
- def create_inverted bundle
39
+ def create_inverted bundle, _ = nil
40
40
  List.new client, "#{PICKY_ENVIRONMENT}:#{bundle.identifier}:inverted", realtime: realtime
41
41
  end
42
42
  # Returns an object that on #initial, #load returns an object that responds to:
43
43
  # [:token] # => 1.23 (a weight)
44
44
  #
45
- def create_weights bundle
45
+ def create_weights bundle, _ = nil
46
46
  Float.new client, "#{PICKY_ENVIRONMENT}:#{bundle.identifier}:weights", realtime: realtime
47
47
  end
48
48
  # Returns an object that on #initial, #load returns an object that responds to:
49
49
  # [:encoded] # => [:original, :original] (an array of original symbols this similarity encoded thing maps to)
50
50
  #
51
- def create_similarity bundle
51
+ def create_similarity bundle, _ = nil
52
52
  List.new client, "#{PICKY_ENVIRONMENT}:#{bundle.identifier}:similarity", realtime: realtime
53
53
  end
54
54
  # Returns an object that on #initial, #load returns an object that responds to:
55
55
  # [:key] # => value (a value for this config key)
56
56
  #
57
- def create_configuration bundle
57
+ def create_configuration bundle, _ = nil
58
58
  String.new client, "#{PICKY_ENVIRONMENT}:#{bundle.identifier}:configuration", realtime: realtime
59
59
  end
60
60
  # Returns an object that on #initial, #load returns an object that responds to:
61
61
  # [id] # => [:sym1, :sym2]
62
62
  #
63
- def create_realtime bundle
63
+ def create_realtime bundle, _ = nil
64
64
  List.new client, "#{PICKY_ENVIRONMENT}:#{bundle.identifier}:realtime", realtime: realtime
65
65
  end
66
66
 
@@ -17,31 +17,31 @@ module Picky
17
17
  # Returns an object that on #initial, #load returns an object that responds to:
18
18
  # [:token] # => [id, id, id, id, id] (an array of ids)
19
19
  #
20
- def create_inverted bundle
20
+ def create_inverted bundle, _ = nil
21
21
  StringKeyArray.new bundle.index_path(:inverted), realtime: realtime
22
22
  end
23
23
  # Returns an object that on #initial, #load returns an object that responds to:
24
24
  # [:token] # => 1.23 (a weight)
25
25
  #
26
- def create_weights bundle
26
+ def create_weights bundle, _ = nil
27
27
  Value.new bundle.index_path(:weights), realtime: realtime
28
28
  end
29
29
  # Returns an object that on #initial, #load returns an object that responds to:
30
30
  # [:encoded] # => [:original, :original] (an array of original symbols this similarity encoded thing maps to)
31
31
  #
32
- def create_similarity bundle
32
+ def create_similarity bundle, _ = nil
33
33
  StringKeyArray.new bundle.index_path(:similarity), realtime: realtime
34
34
  end
35
35
  # Returns an object that on #initial, #load returns an object that responds to:
36
36
  # [:key] # => value (a value for this config key)
37
37
  #
38
- def create_configuration bundle
38
+ def create_configuration bundle, _ = nil
39
39
  Value.new bundle.index_path(:configuration), realtime: realtime
40
40
  end
41
41
  # Returns an object that on #initial, #load returns an object that responds to:
42
42
  # [id] # => [:sym1, :sym2]
43
43
  #
44
- def create_realtime bundle
44
+ def create_realtime bundle, _ = nil
45
45
  IntegerKeyArray.new bundle.index_path(:realtime), realtime: realtime
46
46
  end
47
47
 
data/lib/picky/bundle.rb CHANGED
@@ -53,7 +53,8 @@ module Picky
53
53
  @weight_strategy = weight_strategy
54
54
  @partial_strategy = partial_strategy
55
55
  @similarity_strategy = similarity_strategy
56
-
56
+
57
+ @hints = options.delete :hints
57
58
  @backend = options.delete :backend
58
59
 
59
60
  reset_backend
@@ -81,11 +82,11 @@ module Picky
81
82
  # TODO Move @backend_ into the backend?
82
83
  #
83
84
  def create_backends
84
- @backend_inverted = backend.create_inverted self
85
- @backend_weights = backend.create_weights self
86
- @backend_similarity = backend.create_similarity self
87
- @backend_configuration = backend.create_configuration self
88
- @backend_realtime = backend.create_realtime self
85
+ @backend_inverted = backend.create_inverted self, @hints
86
+ @backend_weights = backend.create_weights self, @hints
87
+ @backend_similarity = backend.create_similarity self, @hints
88
+ @backend_configuration = backend.create_configuration self, @hints
89
+ @backend_realtime = backend.create_realtime self, @hints
89
90
  end
90
91
 
91
92
  # Initial indexes.
@@ -36,6 +36,10 @@ module Picky
36
36
  def initialize name, index, options = {}
37
37
  @name = name
38
38
  @index = index
39
+
40
+ # TODO Move.
41
+ #
42
+ options[:hints] = index.hints
39
43
 
40
44
  configure_from options
41
45
  configure_indexes_from options
@@ -77,7 +81,19 @@ module Picky
77
81
  #
78
82
  # TODO Rewrite it such that this does not need to be maintained separately (and gets available options automatically).
79
83
  #
80
- @@known_keys = [:indexing, :partial, :qualifier, :qualifiers, :ranging, :similarity, :source, :tokenize, :tokenizer, :weight]
84
+ @@known_keys = [
85
+ :hints,
86
+ :indexing,
87
+ :partial,
88
+ :qualifier,
89
+ :qualifiers,
90
+ :ranging,
91
+ :similarity,
92
+ :source,
93
+ :tokenize,
94
+ :tokenizer,
95
+ :weight,
96
+ ]
81
97
  def warn_if_unknown options
82
98
  if options && (options.keys - @@known_keys).size > 0
83
99
  warn <<-WARNING
@@ -0,0 +1,37 @@
1
+ module Picky
2
+ class Index
3
+
4
+ class Hints
5
+
6
+ def initialize hints
7
+ @hints = check hints
8
+ end
9
+
10
+ # Check if all hints are allowed
11
+ #
12
+ @@allowed_hints = [:no_dump]
13
+ def check hints
14
+ hints.each do |hint|
15
+ unless @@allowed_hints.include?(hint)
16
+ raise <<-ERROR
17
+ Picky cannot optimize for #{hint}.
18
+ Allowed hints are:
19
+ #{@@allowed_hints.join("\n")}
20
+ ERROR
21
+ end
22
+ end
23
+ hints
24
+ end
25
+
26
+ # Tells us if the user intends to e.g. not dump the indexes.
27
+ #
28
+ # E.g. hints.does?(:no_dump) # => true/false
29
+ #
30
+ def does? hint
31
+ @hints.include? hint
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ end
data/lib/picky/index.rb CHANGED
@@ -87,7 +87,8 @@ module Picky
87
87
  class Index
88
88
 
89
89
  attr_reader :name,
90
- :categories
90
+ :categories,
91
+ :hints
91
92
 
92
93
  forward :[],
93
94
  :dump,
@@ -126,6 +127,13 @@ module Picky
126
127
 
127
128
  instance_eval(&Proc.new) if block_given?
128
129
  end
130
+
131
+ # Provide hints for Picky so it can optimise.
132
+ #
133
+ def optimize *hints
134
+ require_relative 'index/hints'
135
+ @hints = Hints.new hints
136
+ end
129
137
 
130
138
  # TODO Doc.
131
139
  #
@@ -17,17 +17,17 @@ describe Picky::Bundle do
17
17
  backend: Picky::Backends::Memory.new
18
18
  end
19
19
 
20
- it 'is by default a Hash' do
21
- @bundle.realtime.should be_kind_of(Hash)
20
+ it 'is by default Hash-like' do
21
+ @bundle.realtime.should respond_to(:to_hash)
22
22
  end
23
- it 'is by default a Hash' do
24
- @bundle.inverted.should be_kind_of(Hash)
23
+ it 'is by default Hash-like' do
24
+ @bundle.inverted.should respond_to(:to_hash)
25
25
  end
26
- it 'is by default a Hash' do
27
- @bundle.weights.should be_kind_of(Hash)
26
+ it 'is by default Hash-like' do
27
+ @bundle.weights.should respond_to(:to_hash)
28
28
  end
29
- it 'is by default a Hash' do
30
- @bundle.similarity.should be_kind_of(Hash)
29
+ it 'is by default Hash-like' do
30
+ @bundle.similarity.should respond_to(:to_hash)
31
31
  end
32
32
 
33
33
  context 'strings' do
@@ -5,19 +5,19 @@ require 'spec_helper'
5
5
  # To test the interface definition.
6
6
  #
7
7
  class BackendInterfaceTester < Picky::Backends::Backend
8
- def create_inverted _
8
+ def create_inverted _, _ = nil
9
9
  InternalBackendInterfaceTester.new
10
10
  end
11
- def create_weights _
11
+ def create_weights _, _ = nil
12
12
  InternalBackendInterfaceTester.new
13
13
  end
14
- def create_similarity _
14
+ def create_similarity _, _ = nil
15
15
  InternalBackendInterfaceTester.new
16
16
  end
17
- def create_configuration _
17
+ def create_configuration _, _ = nil
18
18
  InternalBackendInterfaceTester.new
19
19
  end
20
- def create_realtime _
20
+ def create_realtime _, _ = nil
21
21
  InternalBackendInterfaceTester.new
22
22
  end
23
23
  end
@@ -174,14 +174,14 @@ describe 'facets' do
174
174
  end
175
175
  it 'has two filtered facets' do
176
176
  finder.facets(:surname, filter: 'age:40 name:peter', counts: false).should == [
177
- 'kunz',
178
- 'hanke'
177
+ 'hanke',
178
+ 'kunz'
179
179
  ]
180
180
  end
181
181
  it 'has 2 facets >= count 1' do
182
182
  finder.facets(:surname, filter: 'age:40 name:peter', at_least: 1, counts: false).should == [
183
- 'kunz',
184
- 'hanke'
183
+ 'hanke',
184
+ 'kunz'
185
185
  ]
186
186
  end
187
187
  it 'has 0 facets >= counts 2' do
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+ #
3
+ require 'spec_helper'
4
+ require 'ostruct'
5
+
6
+ describe "Hint: no_dump" do
7
+
8
+ Book = Struct.new(:id, :title, :author)
9
+
10
+ let(:index) do
11
+ Picky::Index.new :no_dump do
12
+ optimize :no_dump
13
+
14
+ category :title
15
+ category :author
16
+ end
17
+ end
18
+ let(:try) { Picky::Search.new index }
19
+
20
+ it 'can index and search' do
21
+ index.replace Book.new(2, "Title", "Author")
22
+
23
+ try.search("title:title").ids.should == [2]
24
+ end
25
+
26
+ context 'dumping and loading' do
27
+ it "raises" do
28
+ index.replace Book.new(2, "Title New", "Author New")
29
+
30
+ index.dump
31
+ index.load
32
+ index.build_realtime_mapping
33
+ end
34
+ end
35
+
36
+ end
@@ -27,6 +27,7 @@ describe Picky::Backends::Memory::Basic do
27
27
  context 'with options' do
28
28
  let(:basic) do
29
29
  described_class.new 'spec/temp/some/cache/path/to/file',
30
+ Hash,
30
31
  empty: [],
31
32
  initial: []
32
33
  end
@@ -52,7 +52,7 @@ describe Picky::Category do
52
52
  category.should_receive(:warn).once.with <<-WARNING
53
53
 
54
54
  Warning: Category options {:weights=>:some_weight} for category some_category contain an unknown option.
55
- Working options are: [:indexing, :partial, :qualifier, :qualifiers, :ranging, :similarity, :source, :tokenize, :tokenizer, :weight].
55
+ Working options are: [:hints, :indexing, :partial, :qualifier, :qualifiers, :ranging, :similarity, :source, :tokenize, :tokenizer, :weight].
56
56
  WARNING
57
57
 
58
58
  category.warn_if_unknown :weights => :some_weight
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: picky
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.26.2
4
+ version: 4.27.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Hanke
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2009.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: google_hash
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.8'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.8'
55
69
  description: Fast Ruby semantic text search engine with comfortable single field interface.
56
70
  email: florian.hanke+picky@gmail.com
57
71
  executables:
@@ -73,6 +87,7 @@ files:
73
87
  - lib/picky/backends/file.rb
74
88
  - lib/picky/backends/file/basic.rb
75
89
  - lib/picky/backends/file/json.rb
90
+ - lib/picky/backends/google_hash.rb
76
91
  - lib/picky/backends/helpers/file.rb
77
92
  - lib/picky/backends/memory.rb
78
93
  - lib/picky/backends/memory/basic.rb
@@ -147,6 +162,7 @@ files:
147
162
  - lib/picky/helpers/indexing.rb
148
163
  - lib/picky/helpers/measuring.rb
149
164
  - lib/picky/index.rb
165
+ - lib/picky/index/hints.rb
150
166
  - lib/picky/index_convenience.rb
151
167
  - lib/picky/index_facets.rb
152
168
  - lib/picky/index_indexed.rb
@@ -234,6 +250,7 @@ files:
234
250
  - spec/functional/ignore_spec.rb
235
251
  - spec/functional/max_allocations_spec.rb
236
252
  - spec/functional/multi_index_qualifier_spec.rb
253
+ - spec/functional/no_dump_hint_spec.rb
237
254
  - spec/functional/no_tokenize_spec.rb
238
255
  - spec/functional/non_specific_ids_larger_than_20_spec.rb
239
256
  - spec/functional/object_use_spec.rb
@@ -417,6 +434,7 @@ test_files:
417
434
  - spec/functional/ignore_spec.rb
418
435
  - spec/functional/max_allocations_spec.rb
419
436
  - spec/functional/multi_index_qualifier_spec.rb
437
+ - spec/functional/no_dump_hint_spec.rb
420
438
  - spec/functional/no_tokenize_spec.rb
421
439
  - spec/functional/non_specific_ids_larger_than_20_spec.rb
422
440
  - spec/functional/object_use_spec.rb