picky 3.6.8 → 3.6.9

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.
@@ -31,7 +31,7 @@ module Picky
31
31
  # together.
32
32
  #
33
33
  def empty
34
- @empty && @empty.clone || (@immediate ? self : {})
34
+ @empty && @empty.clone || (@immediate ? self.reset : {})
35
35
  end
36
36
 
37
37
  # The initial content before loading.
@@ -40,7 +40,7 @@ module Picky
40
40
  # this just returns the same thing as #load.
41
41
  #
42
42
  def initial
43
- @initial && @initial.clone || (@immediate ? self : {})
43
+ @initial && @initial.clone || (@immediate ? self.reset : {})
44
44
  end
45
45
 
46
46
  # Returns itself.
@@ -55,6 +55,13 @@ module Picky
55
55
  # Nothing.
56
56
  end
57
57
 
58
+ # Clears the whole namespace.
59
+ #
60
+ def reset
61
+ clear
62
+ self
63
+ end
64
+
58
65
  #
59
66
  #
60
67
  def to_s
@@ -13,8 +13,12 @@ module Picky
13
13
  # Note: Works like the StringHash method, but
14
14
  # returns a float corresponding to that string.
15
15
  #
16
+ # Note: nil.to_f returns 0.0. That's why the
17
+ # code below looks a bit funny.
18
+ #
16
19
  def [] key
17
- super.to_f
20
+ float = super
21
+ float && float.to_f
18
22
  end
19
23
 
20
24
  end
@@ -21,7 +21,7 @@ module Picky
21
21
  # Deletes the list for the key.
22
22
  #
23
23
  def delete key
24
- client.del key
24
+ client.del "#{namespace}:#{key}"
25
25
  end
26
26
 
27
27
  # Writes the hash into Redis.
@@ -61,6 +61,7 @@ module Picky
61
61
  i += 1
62
62
  client.zadd redis_key, i, value
63
63
  end
64
+
64
65
  self[key] # TODO Performance?
65
66
  end
66
67
 
@@ -101,6 +101,11 @@ module Picky
101
101
  # Move this method to the actual backends?
102
102
  #
103
103
  def ids combinations, amount, offset
104
+ # TODO FIXME This is actually not correct:
105
+ # A dumped/loaded Redis backend should use
106
+ # the Redis backend calculation method.
107
+ # So loaded? would be more appropriate.
108
+ #
104
109
  if immediate
105
110
  # Just checked once on the first call.
106
111
  #
@@ -6,9 +6,15 @@ module Picky
6
6
 
7
7
  class Array < Basic
8
8
 
9
+ def create_table
10
+ db.execute 'create table key_value (key varchar(255), value text);'
11
+ end
12
+
9
13
  def []= key, array
10
- if array.empty?
11
- db.execute 'insert or replace into key_value (key, value) values (?,?)', key.to_s, Yajl::Encoder.encode(array)
14
+ unless array.empty?
15
+ db.execute 'INSERT OR REPLACE INTO key_value (key,value) VALUES (?,?)',
16
+ key.to_s,
17
+ Yajl::Encoder.encode(array)
12
18
  end
13
19
 
14
20
  DirectlyManipulable.make self, array, key
@@ -16,9 +22,10 @@ module Picky
16
22
  end
17
23
 
18
24
  def [] key
19
- res = db.execute "select value from key_value where key = ? limit 1;", key.to_s
25
+ res = db.execute "SELECT value FROM key_value WHERE key = ? LIMIT 1",
26
+ key.to_s
20
27
 
21
- return res unless res
28
+ return nil unless res
22
29
 
23
30
  array = res.empty? ? [] : Yajl::Parser.parse(res.first.first)
24
31
  DirectlyManipulable.make self, array, key
@@ -26,7 +33,7 @@ module Picky
26
33
  end
27
34
 
28
35
  def delete key
29
- db.execute "delete from key_value where key = (?)", key.to_s
36
+ db.execute "DELETE FROM key_value WHERE key = (?)", key.to_s
30
37
  end
31
38
 
32
39
  end
@@ -20,11 +20,11 @@ module Picky
20
20
  end
21
21
 
22
22
  def initial
23
- @initial && @initial.clone || (@self_indexed ? self : {})
23
+ @initial && @initial.clone || (@self_indexed ? self.reset : {})
24
24
  end
25
25
 
26
26
  def empty
27
- @empty && @empty.clone || (@self_indexed ? self.reset_db.asynchronous : {})
27
+ @empty && @empty.clone || (@self_indexed ? self.reset.asynchronous : {})
28
28
  end
29
29
 
30
30
  def dump internal
@@ -45,7 +45,7 @@ module Picky
45
45
  end
46
46
 
47
47
  def dump_sqlite internal
48
- reset_db
48
+ reset
49
49
 
50
50
  transaction do
51
51
  # Note: Internal structures need to
@@ -58,17 +58,24 @@ module Picky
58
58
  end
59
59
  end
60
60
 
61
- def reset_db
61
+ def reset
62
62
  create_directory cache_path
63
63
  lazily_initialize_client
64
64
 
65
+ truncate_db
66
+
67
+ self
68
+ end
69
+
70
+ def truncate_db
65
71
  # TODO Could this be replaced by a truncate statement?
66
72
  #
67
- db.execute 'drop table if exists key_value;'
68
- db.execute 'create table key_value (key varchar(255), value text);'
69
- db.execute 'create index key_idx on key_value (key);'
73
+ drop_table
74
+ create_table
75
+ end
70
76
 
71
- self
77
+ def drop_table
78
+ db.execute 'drop table if exists key_value;'
72
79
  end
73
80
 
74
81
  def asynchronous
@@ -0,0 +1,19 @@
1
+ module Picky
2
+
3
+ module Backends
4
+
5
+ class SQLite
6
+
7
+ class IntegerKeyArray < Array
8
+
9
+ def create_table
10
+ db.execute 'create table key_value (key integer PRIMARY KEY, value text);'
11
+ end
12
+
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,19 @@
1
+ module Picky
2
+
3
+ module Backends
4
+
5
+ class SQLite
6
+
7
+ class StringKeyArray < Array
8
+
9
+ def create_table
10
+ db.execute 'create table key_value (key varchar(255) PRIMARY KEY, value text);'
11
+ end
12
+
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -6,8 +6,12 @@ module Picky
6
6
 
7
7
  class Value < Basic
8
8
 
9
+ def create_table
10
+ db.execute 'create table key_value (key varchar(255) PRIMARY KEY, value text);'
11
+ end
12
+
9
13
  def []= key, value
10
- db.execute 'insert or replace into key_value (key, value) values (?,?)',
14
+ db.execute 'INSERT OR REPLACE INTO key_value (key, value) VALUES (?,?)',
11
15
  key.to_s,
12
16
  Yajl::Encoder.encode(value)
13
17
 
@@ -15,14 +19,14 @@ module Picky
15
19
  end
16
20
 
17
21
  def [] key
18
- res = db.execute "select value from key_value where key = ? limit 1;", key.to_s
22
+ res = db.execute "SELECT value FROM key_value WHERE key = ? LIMIT 1;", key.to_s
19
23
  return nil if res.empty?
20
24
 
21
25
  Yajl::Parser.parse res.first.first
22
26
  end
23
27
 
24
28
  def delete key
25
- db.execute "delete from key_value where key = (?)", key.to_s
29
+ db.execute "DELETE FROM key_value WHERE key = (?)", key.to_s
26
30
  end
27
31
 
28
32
  end
@@ -20,7 +20,7 @@ module Picky
20
20
  #
21
21
  def create_inverted bundle
22
22
  extract_lambda_or(inverted, bundle) ||
23
- Array.new(bundle.index_path(:inverted), self_indexed: self_indexed)
23
+ StringKeyArray.new(bundle.index_path(:inverted), self_indexed: self_indexed)
24
24
  end
25
25
  # Returns an object that on #initial, #load returns an object that responds to:
26
26
  # [:token] # => 1.23 (a weight)
@@ -34,7 +34,7 @@ module Picky
34
34
  #
35
35
  def create_similarity bundle
36
36
  extract_lambda_or(similarity, bundle) ||
37
- Array.new(bundle.index_path(:similarity), self_indexed: self_indexed)
37
+ StringKeyArray.new(bundle.index_path(:similarity), self_indexed: self_indexed)
38
38
  end
39
39
  # Returns an object that on #initial, #load returns an object that responds to:
40
40
  # [:key] # => value (a value for this config key)
@@ -48,7 +48,7 @@ module Picky
48
48
  #
49
49
  def create_realtime bundle
50
50
  extract_lambda_or(similarity, bundle) ||
51
- Array.new(bundle.index_path(:realtime), self_indexed: self_indexed)
51
+ IntegerKeyArray.new(bundle.index_path(:realtime), self_indexed: self_indexed)
52
52
  end
53
53
 
54
54
  # Returns the result ids for the allocation.
@@ -40,6 +40,8 @@ module Picky
40
40
  ids.delete id
41
41
  ids.send where, id
42
42
  else
43
+ # Update the realtime index.
44
+ #
43
45
  str_or_syms << str_or_sym
44
46
 
45
47
  # TODO Introduce a new method?
data/lib/picky/loader.rb CHANGED
@@ -134,6 +134,8 @@ module Picky
134
134
  load_relative 'backends/sqlite/basic'
135
135
  load_relative 'backends/sqlite/array'
136
136
  load_relative 'backends/sqlite/value'
137
+ load_relative 'backends/sqlite/string_key_array'
138
+ load_relative 'backends/sqlite/integer_key_array'
137
139
 
138
140
  # Indexing and Indexed things.
139
141
  #
@@ -128,6 +128,10 @@ Case sensitive? #{@case_sensitive ? "Yes." : "-"}
128
128
  tokens.reject! &@reject_condition
129
129
  end
130
130
 
131
+ # Case sensitivity.
132
+ #
133
+ # Note: If false, simply downcases the data/query.
134
+ #
131
135
  def case_sensitive case_sensitive
132
136
  @case_sensitive = case_sensitive
133
137
  end
@@ -135,6 +139,9 @@ Case sensitive? #{@case_sensitive ? "Yes." : "-"}
135
139
  !@case_sensitive
136
140
  end
137
141
 
142
+ # The maximum amount of words
143
+ # to pass into the search engine.
144
+ #
138
145
  def max_words amount
139
146
  @max_words = amount
140
147
  end
@@ -0,0 +1,227 @@
1
+ require 'spec_helper'
2
+
3
+ describe Picky::Bundle do
4
+
5
+ before(:each) do
6
+ @index = Picky::Index.new :some_index
7
+ @category = Picky::Category.new :some_category, @index
8
+
9
+ @weights = Picky::Generators::Weights::Default
10
+ @partial = Picky::Generators::Partial::Default
11
+ @similarity = Picky::Generators::Similarity::DoubleMetaphone.new 3
12
+ @bundle = described_class.new :some_name,
13
+ @category,
14
+ @weights,
15
+ @partial,
16
+ @similarity,
17
+ backend: Picky::Backends::Memory.new
18
+ end
19
+
20
+ it 'is by default an SQLite Array' do
21
+ @bundle.realtime.should be_kind_of(Hash)
22
+ end
23
+ it 'is by default an SQLite Array' do
24
+ @bundle.inverted.should be_kind_of(Hash)
25
+ end
26
+ it 'is by default an SQLite Value' do
27
+ @bundle.weights.should be_kind_of(Hash)
28
+ end
29
+ it 'is by default an SQLite Array' do
30
+ @bundle.similarity.should be_kind_of(Hash)
31
+ end
32
+
33
+ context 'strings' do
34
+ describe 'combined' do
35
+ it 'works correctly' do
36
+ @bundle.add 1, 'title'
37
+ @bundle.add 2, 'title'
38
+
39
+ @bundle.realtime[1].should == ['title']
40
+ @bundle.realtime[2].should == ['title']
41
+ @bundle.inverted['title'].should == [2,1]
42
+ @bundle.weights['title'].should == 0.693
43
+ @bundle.similarity['TTL'].should == ['title']
44
+ end
45
+ it 'works correctly' do
46
+ @bundle.add 1, 'title'
47
+ @bundle.add 2, 'title'
48
+ @bundle.remove 1
49
+ @bundle.remove 2
50
+
51
+ @bundle.realtime[1].should == nil
52
+ @bundle.realtime[2].should == nil
53
+ @bundle.inverted['title'].should == nil
54
+ @bundle.weights['title'].should == nil
55
+ @bundle.similarity['TTL'].should == nil
56
+ end
57
+ it 'works correctly' do
58
+ @bundle.add 1, 'title'
59
+ @bundle.add 1, 'other'
60
+ @bundle.add 1, 'whatever'
61
+ @bundle.remove 1
62
+
63
+ @bundle.realtime[1].should == nil
64
+ @bundle.realtime[2].should == nil
65
+ @bundle.inverted['title'].should == nil
66
+ @bundle.weights['title'].should == nil
67
+ @bundle.similarity['TTL'].should == nil
68
+ end
69
+ it 'works correctly' do
70
+ @bundle.add 1, 'title'
71
+ @bundle.add 2, 'thing'
72
+ @bundle.add 1, 'other'
73
+ @bundle.remove 1
74
+
75
+ @bundle.realtime[1].should == nil
76
+ @bundle.realtime[2].should == ['thing']
77
+ @bundle.inverted['thing'].should == [2]
78
+ @bundle.weights['thing'].should == 0.0
79
+ @bundle.similarity['0NK'].should == ['thing']
80
+ end
81
+ it 'works correctly' do
82
+ @bundle.add 1, 'title'
83
+ @bundle.add 1, 'title'
84
+
85
+ @bundle.realtime[1].should == ['title']
86
+ @bundle.inverted['title'].should == [1]
87
+ @bundle.weights['title'].should == 0.0
88
+ @bundle.similarity['TTL'].should == ['title']
89
+ end
90
+ it 'works correctly' do
91
+ @bundle.add 1, 'title'
92
+ @bundle.remove 1
93
+ @bundle.remove 1
94
+
95
+ @bundle.realtime[1].should == nil
96
+ @bundle.inverted['title'].should == nil
97
+ @bundle.weights['title'].should == nil
98
+ @bundle.similarity['TTL'].should == nil
99
+ end
100
+ end
101
+
102
+ describe 'add' do
103
+ it 'works correctly' do
104
+ @bundle.add 1, 'title'
105
+
106
+ @bundle.realtime[1].should == ['title']
107
+
108
+ @bundle.add 2, 'other'
109
+
110
+ @bundle.realtime[1].should == ['title']
111
+ @bundle.realtime[2].should == ['other']
112
+
113
+ @bundle.add 1, 'thing'
114
+
115
+ @bundle.realtime[1].should == ['title', 'thing']
116
+ @bundle.realtime[2].should == ['other']
117
+ end
118
+ it 'works correctly' do
119
+ @bundle.add 1, 'title'
120
+
121
+ @bundle.weights['title'].should == 0.0
122
+ @bundle.inverted['title'].should == [1]
123
+ @bundle.similarity['TTL'].should == ['title']
124
+ end
125
+ end
126
+ end
127
+
128
+ context 'symbols' do
129
+ describe 'combined' do
130
+ it 'works correctly' do
131
+ @bundle.add 1, :title
132
+ @bundle.add 2, :title
133
+
134
+ @bundle.realtime.should == { 1 => [:title], 2 => [:title] }
135
+ @bundle.inverted.should == { :title => [2,1] }
136
+ @bundle.weights.should == { :title => 0.693 }
137
+ @bundle.similarity.should == { :TTL => [:title] }
138
+
139
+ @bundle.realtime[1].should == [:title]
140
+ @bundle.realtime[2].should == [:title]
141
+ @bundle.inverted[:title].should == [2,1]
142
+ @bundle.weights[:title].should == 0.693
143
+ @bundle.similarity[:TTL].should == [:title]
144
+ end
145
+ it 'works correctly' do
146
+ @bundle.add 1, :title
147
+ @bundle.add 2, :title
148
+ @bundle.remove 1
149
+ @bundle.remove 2
150
+
151
+ @bundle.realtime[1].should == nil
152
+ @bundle.realtime[2].should == nil
153
+ @bundle.inverted[:title].should == nil
154
+ @bundle.weights[:title].should == nil
155
+ @bundle.similarity[:TTL].should == nil
156
+ end
157
+ it 'works correctly' do
158
+ @bundle.add 1, :title
159
+ @bundle.add 1, :other
160
+ @bundle.add 1, :whatever
161
+ @bundle.remove 1
162
+
163
+ @bundle.realtime[1].should == nil
164
+ @bundle.inverted[:title].should == nil
165
+ @bundle.weights[:title].should == nil
166
+ @bundle.similarity[:TTL].should == nil
167
+ end
168
+ it 'works correctly' do
169
+ @bundle.add 1, :title
170
+ @bundle.add 2, :thing
171
+ @bundle.add 1, :other
172
+ @bundle.remove 1
173
+
174
+ @bundle.realtime[1].should == nil
175
+ @bundle.realtime[2].should == [:thing]
176
+ @bundle.inverted[:thing].should == [2]
177
+ @bundle.weights[:thing].should == 0.0
178
+ @bundle.similarity[:'0NK'].should == [:thing]
179
+ end
180
+ it 'works correctly' do
181
+ @bundle.add 1, :title
182
+ @bundle.add 1, :title
183
+
184
+ @bundle.realtime[1].should == [:title]
185
+ @bundle.inverted[:title].should == [1]
186
+ @bundle.weights[:title].should == 0.0
187
+ @bundle.similarity[:'TTL'].should == [:title]
188
+ end
189
+ it 'works correctly' do
190
+ @bundle.add 1, :title
191
+ @bundle.remove 1
192
+ @bundle.remove 1
193
+
194
+ @bundle.realtime[1].should == nil
195
+ @bundle.inverted[:title].should == nil
196
+ @bundle.weights[:title].should == nil
197
+ @bundle.similarity[:TTL].should == nil
198
+ end
199
+ end
200
+
201
+ describe 'add' do
202
+ it 'works correctly' do
203
+ @bundle.add 1, :title
204
+
205
+ @bundle.realtime[1].should == [:title]
206
+
207
+ @bundle.add 2, :other
208
+
209
+ @bundle.realtime[1].should == [:title]
210
+ @bundle.realtime[2].should == [:other]
211
+
212
+ @bundle.add 1, :thing
213
+
214
+ @bundle.realtime[1].should == [:title, :thing]
215
+ @bundle.realtime[2].should == [:other]
216
+ end
217
+ it 'works correctly' do
218
+ @bundle.add 1, :title
219
+
220
+ @bundle.weights[:title].should == 0.0
221
+ @bundle.inverted[:title].should == [1]
222
+ @bundle.similarity[:TTL].should == [:title]
223
+ end
224
+ end
225
+ end
226
+
227
+ end
@@ -0,0 +1,224 @@
1
+ require 'spec_helper'
2
+
3
+ describe Picky::Bundle do
4
+
5
+ before(:each) do
6
+ @index = Picky::Index.new :some_index
7
+ @category = Picky::Category.new :some_category, @index
8
+
9
+ @weights = Picky::Generators::Weights::Default
10
+ @partial = Picky::Generators::Partial::Default
11
+ @similarity = Picky::Generators::Similarity::DoubleMetaphone.new 3
12
+ @bundle = described_class.new :some_name,
13
+ @category,
14
+ @weights,
15
+ @partial,
16
+ @similarity,
17
+ backend: Picky::Backends::Redis.new(immediate: true)
18
+ end
19
+
20
+ it 'is by default an SQLite Array' do
21
+ @bundle.realtime.should be_kind_of(Picky::Backends::Redis::List)
22
+ end
23
+ it 'is by default an SQLite Array' do
24
+ @bundle.inverted.should be_kind_of(Picky::Backends::Redis::List)
25
+ end
26
+ it 'is by default an SQLite Value' do
27
+ @bundle.weights.should be_kind_of(Picky::Backends::Redis::Float)
28
+ end
29
+ it 'is by default an SQLite Array' do
30
+ @bundle.similarity.should be_kind_of(Picky::Backends::Redis::List)
31
+ end
32
+
33
+ context 'strings' do
34
+ describe 'combined' do
35
+ it 'works correctly' do
36
+ @bundle.add '1', 'title'
37
+ @bundle.add '2', 'title'
38
+
39
+ @bundle.realtime['1'].should == ['title']
40
+ @bundle.realtime['2'].should == ['title']
41
+ @bundle.inverted['title'].should == ['2','1']
42
+ @bundle.weights['title'].should == 0.693
43
+ @bundle.similarity['TTL'].should == ['title']
44
+ end
45
+ it 'works correctly' do
46
+ @bundle.add '1', 'title'
47
+ @bundle.add '2', 'title'
48
+ @bundle.remove '1'
49
+ @bundle.remove '2'
50
+
51
+ @bundle.realtime['1'].should == []
52
+ @bundle.realtime['2'].should == []
53
+ @bundle.inverted['title'].should == []
54
+ @bundle.weights['title'].should == nil
55
+ @bundle.similarity['TTL'].should == []
56
+ end
57
+ it 'works correctly' do
58
+ @bundle.add '1', 'title'
59
+ @bundle.add '1', 'other'
60
+ @bundle.add '1', 'whatever'
61
+ @bundle.remove '1'
62
+
63
+ @bundle.realtime['1'].should == []
64
+ @bundle.realtime['2'].should == []
65
+ @bundle.inverted['title'].should == []
66
+ @bundle.weights['title'].should == nil
67
+ @bundle.similarity['TTL'].should == []
68
+ end
69
+ it 'works correctly' do
70
+ @bundle.add '1', 'title'
71
+ @bundle.add '2', 'thing'
72
+ @bundle.add '1', 'other'
73
+ @bundle.remove '1'
74
+
75
+ @bundle.realtime['1'].should == []
76
+ @bundle.realtime['2'].should == ['thing']
77
+ @bundle.inverted['thing'].should == ['2']
78
+ @bundle.weights['thing'].should == 0.0
79
+ @bundle.similarity['0NK'].should == ['thing']
80
+ end
81
+ it 'works correctly' do
82
+ @bundle.add '1', 'title'
83
+ @bundle.add '1', 'title'
84
+
85
+ @bundle.realtime['1'].should == ['title']
86
+ @bundle.inverted['title'].should == ['1']
87
+ @bundle.weights['title'].should == 0.0
88
+ @bundle.similarity['TTL'].should == ['title']
89
+ end
90
+ it 'works correctly' do
91
+ @bundle.add '1', 'title'
92
+ @bundle.remove '1'
93
+ @bundle.remove '1'
94
+
95
+ @bundle.realtime['1'].should == []
96
+ @bundle.inverted['title'].should == []
97
+ @bundle.weights['title'].should == nil
98
+ @bundle.similarity['TTL'].should == []
99
+ end
100
+ end
101
+
102
+ describe 'add' do
103
+ it 'works correctly' do
104
+ @bundle.add '1', 'title'
105
+
106
+ @bundle.realtime['1'].should == ['title']
107
+
108
+ @bundle.add '2', 'other'
109
+
110
+ @bundle.realtime['1'].should == ['title']
111
+ @bundle.realtime['2'].should == ['other']
112
+
113
+ @bundle.add '1', 'thing'
114
+
115
+ @bundle.realtime['1'].should == ['title', 'thing']
116
+ @bundle.realtime['2'].should == ['other']
117
+ end
118
+ it 'works correctly' do
119
+ @bundle.add '1', 'title'
120
+
121
+ @bundle.weights['title'].should == 0.0
122
+ @bundle.inverted['title'].should == ['1']
123
+ @bundle.similarity['TTL'].should == ['title']
124
+ end
125
+ end
126
+ end
127
+
128
+ # TODO Add symbols.
129
+ #
130
+ # context 'symbols' do
131
+ # describe 'combined' do
132
+ # it 'works correctly' do
133
+ # @bundle.add '1', :title
134
+ # @bundle.add '2', :title
135
+ #
136
+ # @bundle.realtime['1'].should == [:title]
137
+ # @bundle.realtime['2'].should == [:title]
138
+ # @bundle.inverted[:title].should == [2,1]
139
+ # @bundle.weights[:title].should == 0.693
140
+ # @bundle.similarity[:TTL].should == [:title]
141
+ # end
142
+ # it 'works correctly' do
143
+ # @bundle.add '1', :title
144
+ # @bundle.add '2', :title
145
+ # @bundle.remove 1
146
+ # @bundle.remove 2
147
+ #
148
+ # @bundle.realtime['1'].should == []
149
+ # @bundle.realtime['2'].should == []
150
+ # @bundle.inverted[:title].should == []
151
+ # @bundle.weights[:title].should == nil
152
+ # @bundle.similarity[:TTL].should == []
153
+ # end
154
+ # it 'works correctly' do
155
+ # @bundle.add '1', :title
156
+ # @bundle.add '1', :other
157
+ # @bundle.add '1', :whatever
158
+ # @bundle.remove 1
159
+ #
160
+ # @bundle.realtime['1'].should == []
161
+ # @bundle.inverted[:title].should == []
162
+ # @bundle.weights[:title].should == nil
163
+ # @bundle.similarity[:TTL].should == []
164
+ # end
165
+ # it 'works correctly' do
166
+ # @bundle.add '1', :title
167
+ # @bundle.add '2', :thing
168
+ # @bundle.add '1', :other
169
+ # @bundle.remove 1
170
+ #
171
+ # @bundle.realtime['1'].should == []
172
+ # @bundle.realtime['2'].should == [:thing]
173
+ # @bundle.inverted[:thing].should == ['2']
174
+ # @bundle.weights[:thing].should == 0.0
175
+ # @bundle.similarity[:'0NK'].should == [:thing]
176
+ # end
177
+ # it 'works correctly' do
178
+ # @bundle.add '1', :title
179
+ # @bundle.add '1', :title
180
+ #
181
+ # @bundle.realtime['1'].should == [:title]
182
+ # @bundle.inverted[:title].should == ['1']
183
+ # @bundle.weights[:title].should == 0.0
184
+ # @bundle.similarity[:'TTL'].should == [:title]
185
+ # end
186
+ # it 'works correctly' do
187
+ # @bundle.add '1', :title
188
+ # @bundle.remove 1
189
+ # @bundle.remove 1
190
+ #
191
+ # @bundle.realtime['1'].should == []
192
+ # @bundle.inverted[:title].should == []
193
+ # @bundle.weights[:title].should == nil
194
+ # @bundle.similarity[:TTL].should == []
195
+ # end
196
+ # end
197
+ #
198
+ # describe 'add' do
199
+ # it 'works correctly' do
200
+ # @bundle.add '1', :title
201
+ #
202
+ # @bundle.realtime['1'].should == [:title]
203
+ #
204
+ # @bundle.add '2', :other
205
+ #
206
+ # @bundle.realtime['1'].should == [:title]
207
+ # @bundle.realtime['2'].should == [:other]
208
+ #
209
+ # @bundle.add '1', :thing
210
+ #
211
+ # @bundle.realtime['1'].should == [:title, :thing]
212
+ # @bundle.realtime['2'].should == [:other]
213
+ # end
214
+ # it 'works correctly' do
215
+ # @bundle.add '1', :title
216
+ #
217
+ # @bundle.weights[:title].should == 0.0
218
+ # @bundle.inverted[:title].should == ['1']
219
+ # @bundle.similarity[:TTL].should == [:title]
220
+ # end
221
+ # end
222
+ # end
223
+
224
+ end
@@ -93,15 +93,15 @@ describe Picky::Backends::Redis do
93
93
  instance_eval &its
94
94
  end
95
95
 
96
- # context 'immediately indexing backend (no dump needed)' do
97
- # before(:each) do
98
- # data.backend Picky::Backends::Redis.new(immediate: true)
99
- # data.clear
100
- #
101
- # data.add Book.new(1, 'title', 'author')
102
- # end
103
- #
104
- # instance_eval &its
105
- # end
96
+ context 'immediately indexing backend (no dump needed)' do
97
+ before(:each) do
98
+ data.backend Picky::Backends::Redis.new(immediate: true)
99
+ data.clear
100
+
101
+ data.add Book.new(1, 'title', 'author')
102
+ end
103
+
104
+ instance_eval &its
105
+ end
106
106
 
107
107
  end
@@ -0,0 +1,224 @@
1
+ require 'spec_helper'
2
+
3
+ describe Picky::Bundle do
4
+
5
+ before(:each) do
6
+ @index = Picky::Index.new :some_index
7
+ @category = Picky::Category.new :some_category, @index
8
+
9
+ @weights = Picky::Generators::Weights::Default
10
+ @partial = Picky::Generators::Partial::Default
11
+ @similarity = Picky::Generators::Similarity::DoubleMetaphone.new 3
12
+ @bundle = described_class.new :some_name,
13
+ @category,
14
+ @weights,
15
+ @partial,
16
+ @similarity,
17
+ backend: Picky::Backends::SQLite.new(self_indexed: true)
18
+ end
19
+
20
+ it 'is by default an SQLite Array' do
21
+ @bundle.realtime.should be_kind_of(Picky::Backends::SQLite::Array)
22
+ end
23
+ it 'is by default an SQLite Array' do
24
+ @bundle.inverted.should be_kind_of(Picky::Backends::SQLite::Array)
25
+ end
26
+ it 'is by default an SQLite Value' do
27
+ @bundle.weights.should be_kind_of(Picky::Backends::SQLite::Value)
28
+ end
29
+ it 'is by default an SQLite Array' do
30
+ @bundle.similarity.should be_kind_of(Picky::Backends::SQLite::Array)
31
+ end
32
+
33
+ context 'strings' do
34
+ describe 'combined' do
35
+ it 'works correctly' do
36
+ @bundle.add 1, 'title'
37
+ @bundle.add 2, 'title'
38
+
39
+ @bundle.realtime[1].should == ['title']
40
+ @bundle.realtime[2].should == ['title']
41
+ @bundle.inverted['title'].should == [2,1]
42
+ @bundle.weights['title'].should == 0.693
43
+ @bundle.similarity['TTL'].should == ['title']
44
+ end
45
+ it 'works correctly' do
46
+ @bundle.add 1, 'title'
47
+ @bundle.add 2, 'title'
48
+ @bundle.remove 1
49
+ @bundle.remove 2
50
+
51
+ @bundle.realtime[1].should == []
52
+ @bundle.realtime[2].should == []
53
+ @bundle.inverted['title'].should == []
54
+ @bundle.weights['title'].should == nil
55
+ @bundle.similarity['TTL'].should == []
56
+ end
57
+ it 'works correctly' do
58
+ @bundle.add 1, 'title'
59
+ @bundle.add 1, 'other'
60
+ @bundle.add 1, 'whatever'
61
+ @bundle.remove 1
62
+
63
+ @bundle.realtime[1].should == []
64
+ @bundle.realtime[2].should == []
65
+ @bundle.inverted['title'].should == []
66
+ @bundle.weights['title'].should == nil
67
+ @bundle.similarity['TTL'].should == []
68
+ end
69
+ it 'works correctly' do
70
+ @bundle.add 1, 'title'
71
+ @bundle.add 2, 'thing'
72
+ @bundle.add 1, 'other'
73
+ @bundle.remove 1
74
+
75
+ @bundle.realtime[1].should == []
76
+ @bundle.realtime[2].should == ['thing']
77
+ @bundle.inverted['thing'].should == [2]
78
+ @bundle.weights['thing'].should == 0.0
79
+ @bundle.similarity['0NK'].should == ['thing']
80
+ end
81
+ it 'works correctly' do
82
+ @bundle.add 1, 'title'
83
+ @bundle.add 1, 'title'
84
+
85
+ @bundle.realtime[1].should == ['title']
86
+ @bundle.inverted['title'].should == [1]
87
+ @bundle.weights['title'].should == 0.0
88
+ @bundle.similarity['TTL'].should == ['title']
89
+ end
90
+ it 'works correctly' do
91
+ @bundle.add 1, 'title'
92
+ @bundle.remove 1
93
+ @bundle.remove 1
94
+
95
+ @bundle.realtime[1].should == []
96
+ @bundle.inverted['title'].should == []
97
+ @bundle.weights['title'].should == nil
98
+ @bundle.similarity['TTL'].should == []
99
+ end
100
+ end
101
+
102
+ describe 'add' do
103
+ it 'works correctly' do
104
+ @bundle.add 1, 'title'
105
+
106
+ @bundle.realtime[1].should == ['title']
107
+
108
+ @bundle.add 2, 'other'
109
+
110
+ @bundle.realtime[1].should == ['title']
111
+ @bundle.realtime[2].should == ['other']
112
+
113
+ @bundle.add 1, 'thing'
114
+
115
+ @bundle.realtime[1].should == ['title', 'thing']
116
+ @bundle.realtime[2].should == ['other']
117
+ end
118
+ it 'works correctly' do
119
+ @bundle.add 1, 'title'
120
+
121
+ @bundle.weights['title'].should == 0.0
122
+ @bundle.inverted['title'].should == [1]
123
+ @bundle.similarity['TTL'].should == ['title']
124
+ end
125
+ end
126
+ end
127
+
128
+ # TODO Add symbols.
129
+ #
130
+ # context 'symbols' do
131
+ # describe 'combined' do
132
+ # it 'works correctly' do
133
+ # @bundle.add 1, :title
134
+ # @bundle.add 2, :title
135
+ #
136
+ # @bundle.realtime[1].should == [:title]
137
+ # @bundle.realtime[2].should == [:title]
138
+ # @bundle.inverted[:title].should == [2,1]
139
+ # @bundle.weights[:title].should == 0.693
140
+ # @bundle.similarity[:TTL].should == [:title]
141
+ # end
142
+ # it 'works correctly' do
143
+ # @bundle.add 1, :title
144
+ # @bundle.add 2, :title
145
+ # @bundle.remove 1
146
+ # @bundle.remove 2
147
+ #
148
+ # @bundle.realtime[1].should == []
149
+ # @bundle.realtime[2].should == []
150
+ # @bundle.inverted[:title].should == []
151
+ # @bundle.weights[:title].should == nil
152
+ # @bundle.similarity[:TTL].should == []
153
+ # end
154
+ # it 'works correctly' do
155
+ # @bundle.add 1, :title
156
+ # @bundle.add 1, :other
157
+ # @bundle.add 1, :whatever
158
+ # @bundle.remove 1
159
+ #
160
+ # @bundle.realtime[1].should == []
161
+ # @bundle.inverted[:title].should == []
162
+ # @bundle.weights[:title].should == nil
163
+ # @bundle.similarity[:TTL].should == []
164
+ # end
165
+ # it 'works correctly' do
166
+ # @bundle.add 1, :title
167
+ # @bundle.add 2, :thing
168
+ # @bundle.add 1, :other
169
+ # @bundle.remove 1
170
+ #
171
+ # @bundle.realtime[1].should == []
172
+ # @bundle.realtime[2].should == [:thing]
173
+ # @bundle.inverted[:thing].should == [2]
174
+ # @bundle.weights[:thing].should == 0.0
175
+ # @bundle.similarity[:'0NK'].should == [:thing]
176
+ # end
177
+ # it 'works correctly' do
178
+ # @bundle.add 1, :title
179
+ # @bundle.add 1, :title
180
+ #
181
+ # @bundle.realtime[1].should == [:title]
182
+ # @bundle.inverted[:title].should == [1]
183
+ # @bundle.weights[:title].should == 0.0
184
+ # @bundle.similarity[:'TTL'].should == [:title]
185
+ # end
186
+ # it 'works correctly' do
187
+ # @bundle.add 1, :title
188
+ # @bundle.remove 1
189
+ # @bundle.remove 1
190
+ #
191
+ # @bundle.realtime[1].should == []
192
+ # @bundle.inverted[:title].should == []
193
+ # @bundle.weights[:title].should == nil
194
+ # @bundle.similarity[:TTL].should == []
195
+ # end
196
+ # end
197
+ #
198
+ # describe 'add' do
199
+ # it 'works correctly' do
200
+ # @bundle.add 1, :title
201
+ #
202
+ # @bundle.realtime[1].should == [:title]
203
+ #
204
+ # @bundle.add 2, :other
205
+ #
206
+ # @bundle.realtime[1].should == [:title]
207
+ # @bundle.realtime[2].should == [:other]
208
+ #
209
+ # @bundle.add 1, :thing
210
+ #
211
+ # @bundle.realtime[1].should == [:title, :thing]
212
+ # @bundle.realtime[2].should == [:other]
213
+ # end
214
+ # it 'works correctly' do
215
+ # @bundle.add 1, :title
216
+ #
217
+ # @bundle.weights[:title].should == 0.0
218
+ # @bundle.inverted[:title].should == [1]
219
+ # @bundle.similarity[:TTL].should == [:title]
220
+ # end
221
+ # end
222
+ # end
223
+
224
+ end
@@ -50,6 +50,16 @@ describe Picky::Backends::SQLite do
50
50
 
51
51
  books.search('title').ids.should == [2]
52
52
  end
53
+ it 'handles removing with three entries' do
54
+ data.add Book.new(2, 'title', 'author')
55
+ data.add Book.new(3, 'title', 'author')
56
+
57
+ books.search('title').ids.should == [3, 2, 1]
58
+
59
+ data.remove 1
60
+
61
+ books.search('title').ids.should == [3, 2]
62
+ end
53
63
  it 'handles clearing' do
54
64
  data.clear
55
65
 
@@ -61,16 +71,6 @@ describe Picky::Backends::SQLite do
61
71
 
62
72
  books.search('title').ids.should == [1]
63
73
  end
64
- it 'handles removing with three entries' do
65
- data.add Book.new(2, 'title', 'author')
66
- data.add Book.new(3, 'title', 'author')
67
-
68
- books.search('title').ids.should == [3, 2, 1]
69
-
70
- data.remove 1
71
-
72
- books.search('title').ids.should == [3, 2]
73
- end
74
74
  it 'handles replacing' do
75
75
  data.replace Book.new(1, 'toitle', 'oithor')
76
76
 
@@ -90,15 +90,15 @@ describe Picky::Backends::SQLite do
90
90
  instance_eval &its
91
91
  end
92
92
 
93
- # context 'immediately indexing backend (no dump needed)' do
94
- # before(:each) do
95
- # data.backend described_class.new(self_indexed: true)
96
- # data.clear
97
- #
98
- # data.add Book.new(1, 'title', 'author')
99
- # end
100
- #
101
- # instance_eval &its
102
- # end
93
+ context 'immediately indexing backend (no dump needed)' do
94
+ before(:each) do
95
+ data.backend described_class.new(self_indexed: true)
96
+ data.clear
97
+
98
+ data.add Book.new(1, 'title', 'author')
99
+ end
100
+
101
+ instance_eval &its
102
+ end
103
103
 
104
104
  end
@@ -30,4 +30,35 @@ describe 'Search#max_allocations' do
30
30
  try_again.search('hello world').ids.should == [1]
31
31
  end
32
32
 
33
+ it 'gets faster' do
34
+ index = Picky::Index.new :dynamic_weights do
35
+ category :text1
36
+ category :text2
37
+ category :text3
38
+ category :text4
39
+ end
40
+
41
+ thing = Struct.new(:id, :text1, :text2, :text3, :text4)
42
+ index.add thing.new(1, 'hello world', 'hello world', 'hello world', 'hello world')
43
+ index.add thing.new(2, 'hello world', 'hello world', 'hello world', 'hello world')
44
+ index.add thing.new(3, 'hello world', 'hello world', 'hello world', 'hello world')
45
+ index.add thing.new(4, 'hello world', 'hello world', 'hello world', 'hello world')
46
+ index.add thing.new(5, 'hello world', 'hello world', 'hello world', 'hello world')
47
+ index.add thing.new(6, 'hello world', 'hello world', 'hello world', 'hello world')
48
+
49
+ try = Picky::Search.new index
50
+
51
+ threshold = performance_of do
52
+ try.search('hello world')
53
+ end
54
+
55
+ try_again = Picky::Search.new index do
56
+ max_allocations 1
57
+ end
58
+
59
+ performance_of do
60
+ try_again.search('hello world')
61
+ end.should < (threshold*2/3)
62
+ end
63
+
33
64
  end
@@ -27,6 +27,11 @@ describe Picky::Backends::Redis::Float do
27
27
 
28
28
  backend['anything'].should == 1.23
29
29
  end
30
+ it 'returns whatever it gets from the backend' do
31
+ client.should_receive(:hget).any_number_of_times.and_return nil
32
+
33
+ backend['anything'].should == nil
34
+ end
30
35
  end
31
36
 
32
37
  describe 'to_s' do
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: 3.6.8
4
+ version: 3.6.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-29 00:00:00.000000000 Z
12
+ date: 2011-11-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70319172184220 !ruby/object:Gem::Requirement
16
+ requirement: &70133025519700 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,21 +21,21 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70319172184220
24
+ version_requirements: *70133025519700
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: picky-client
27
- requirement: &70319172181920 !ruby/object:Gem::Requirement
27
+ requirement: &70133025518760 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
31
31
  - !ruby/object:Gem::Version
32
- version: 3.6.8
32
+ version: 3.6.9
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70319172181920
35
+ version_requirements: *70133025518760
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rack
38
- requirement: &70319172180560 !ruby/object:Gem::Requirement
38
+ requirement: &70133025518340 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70319172180560
46
+ version_requirements: *70133025518340
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rack_fast_escape
49
- requirement: &70319172222400 !ruby/object:Gem::Requirement
49
+ requirement: &70133025517860 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70319172222400
57
+ version_requirements: *70133025517860
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: text
60
- requirement: &70319172220440 !ruby/object:Gem::Requirement
60
+ requirement: &70133025517220 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70319172220440
68
+ version_requirements: *70133025517220
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yajl-ruby
71
- requirement: &70319172237300 !ruby/object:Gem::Requirement
71
+ requirement: &70133025516620 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *70319172237300
79
+ version_requirements: *70133025516620
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: activesupport
82
- requirement: &70319172277680 !ruby/object:Gem::Requirement
82
+ requirement: &70133025515700 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '3.0'
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *70319172277680
90
+ version_requirements: *70133025515700
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: unicorn
93
- requirement: &70319172274760 !ruby/object:Gem::Requirement
93
+ requirement: &70133025514840 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :runtime
100
100
  prerelease: false
101
- version_requirements: *70319172274760
101
+ version_requirements: *70133025514840
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: sinatra
104
- requirement: &70319172284740 !ruby/object:Gem::Requirement
104
+ requirement: &70133025513920 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,7 +109,7 @@ dependencies:
109
109
  version: '0'
110
110
  type: :runtime
111
111
  prerelease: false
112
- version_requirements: *70319172284740
112
+ version_requirements: *70133025513920
113
113
  description: Fast Ruby semantic text search engine with comfortable single field interface.
114
114
  email: florian.hanke+picky@gmail.com
115
115
  executables:
@@ -146,6 +146,8 @@ files:
146
146
  - lib/picky/backends/sqlite/array.rb
147
147
  - lib/picky/backends/sqlite/basic.rb
148
148
  - lib/picky/backends/sqlite/directly_manipulable.rb
149
+ - lib/picky/backends/sqlite/integer_key_array.rb
150
+ - lib/picky/backends/sqlite/string_key_array.rb
149
151
  - lib/picky/backends/sqlite/value.rb
150
152
  - lib/picky/backends/sqlite.rb
151
153
  - lib/picky/bundle.rb
@@ -261,8 +263,11 @@ files:
261
263
  - spec/category_realtime_spec.rb
262
264
  - spec/ext/performant_spec.rb
263
265
  - spec/functional/backends/file_spec.rb
266
+ - spec/functional/backends/memory_bundle_realtime_spec.rb
264
267
  - spec/functional/backends/memory_spec.rb
268
+ - spec/functional/backends/redis_bundle_realtime_spec.rb
265
269
  - spec/functional/backends/redis_spec.rb
270
+ - spec/functional/backends/sqlite_bundle_realtime_spec.rb
266
271
  - spec/functional/backends/sqlite_spec.rb
267
272
  - spec/functional/dynamic_weights_spec.rb
268
273
  - spec/functional/exact_first_spec.rb
@@ -401,8 +406,11 @@ test_files:
401
406
  - spec/category_realtime_spec.rb
402
407
  - spec/ext/performant_spec.rb
403
408
  - spec/functional/backends/file_spec.rb
409
+ - spec/functional/backends/memory_bundle_realtime_spec.rb
404
410
  - spec/functional/backends/memory_spec.rb
411
+ - spec/functional/backends/redis_bundle_realtime_spec.rb
405
412
  - spec/functional/backends/redis_spec.rb
413
+ - spec/functional/backends/sqlite_bundle_realtime_spec.rb
406
414
  - spec/functional/backends/sqlite_spec.rb
407
415
  - spec/functional/dynamic_weights_spec.rb
408
416
  - spec/functional/exact_first_spec.rb