picky 4.30.0 → 4.31.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 +4 -4
- data/lib/picky/backends/file/json.rb +2 -2
- data/lib/picky/backends/memory/json.rb +2 -2
- data/lib/picky/backends/memory/marshal.rb +1 -1
- data/lib/picky/backends/redis/basic.rb +1 -1
- data/lib/picky/backends/sqlite/basic.rb +1 -1
- data/lib/picky/bundle.rb +3 -2
- data/lib/picky/bundle_indexed.rb +18 -18
- data/lib/picky/bundle_realtime.rb +29 -11
- data/lib/picky/category_indexed.rb +23 -8
- data/lib/picky/category_realtime.rb +6 -3
- data/lib/picky/query/token.rb +2 -1
- data/spec/functional/backends/special_spec.rb +1 -1
- data/spec/functional/facets_spec.rb +4 -4
- data/spec/functional/memory_usage_spec.rb +67 -0
- data/spec/functional/realtime_force_update_spec.rb +53 -20
- data/spec/functional/realtime_spec.rb +177 -169
- data/spec/functional/static_spec.rb +2 -2
- data/spec/lib/backends/redis/basic_spec.rb +1 -1
- data/spec/lib/backends/sqlite/array_spec.rb +2 -2
- data/spec/lib/backends/sqlite/value_spec.rb +1 -1
- data/spec/lib/bundle_indexed_spec.rb +7 -7
- data/spec/lib/query/token_spec.rb +2 -4
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1399f4e15ee1e94d7ec6c91ab88b9721702524f6
|
4
|
+
data.tar.gz: 24e20ab22278fddf14d13a3ce5f22319aac4fe7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0948fcb8da05a7174713c5dae9e408eb69808173de4d55dacfba1bdfd024016b63d030293a929973b3c805b29c319afc59bb85959f10609b438c4058fa81897
|
7
|
+
data.tar.gz: 930e22468a92b53f87fa06c51c96b94e3142d6d33457bafa936bebd65f5e14ab5a089d90f4cafb295005c65e157230b3d4e1e2694cb0a0d801c1798e8cf9837b
|
@@ -22,8 +22,8 @@ module Picky
|
|
22
22
|
#
|
23
23
|
# Also ensures all hash keys are frozen.
|
24
24
|
#
|
25
|
-
def load
|
26
|
-
MultiJson.decode ::File.open(cache_path, 'r')
|
25
|
+
def load symbol_keys
|
26
|
+
MultiJson.decode ::File.open(cache_path, 'r'), symbolize_keys: symbol_keys # SYMBOLS.
|
27
27
|
# index_hash && index_hash.each { |(key, value)| key.freeze }
|
28
28
|
# index_hash
|
29
29
|
end
|
data/lib/picky/bundle.rb
CHANGED
@@ -131,10 +131,11 @@ module Picky
|
|
131
131
|
#
|
132
132
|
# Note: Also checks for itself.
|
133
133
|
#
|
134
|
-
def similar
|
135
|
-
code = similarity_strategy.encode
|
134
|
+
def similar str_or_sym
|
135
|
+
code = similarity_strategy.encode str_or_sym
|
136
136
|
return [] unless code
|
137
137
|
@similarity[code] || []
|
138
|
+
|
138
139
|
# similar_codes = @similarity[code]
|
139
140
|
# if similar_codes.blank?
|
140
141
|
# [] # Return a simple array.
|
data/lib/picky/bundle_indexed.rb
CHANGED
@@ -23,8 +23,8 @@ module Picky
|
|
23
23
|
# Note: If the backend wants to return a special
|
24
24
|
# enumerable, the backend should do so.
|
25
25
|
#
|
26
|
-
def ids
|
27
|
-
@inverted[
|
26
|
+
def ids str_or_sym
|
27
|
+
@inverted[str_or_sym] || []
|
28
28
|
# THINK Place the key_format conversion here – or move into the backend?
|
29
29
|
#
|
30
30
|
# if @key_format
|
@@ -46,16 +46,16 @@ module Picky
|
|
46
46
|
#
|
47
47
|
# Returns a number, or nil.
|
48
48
|
#
|
49
|
-
def weight
|
50
|
-
@weights[
|
49
|
+
def weight str_or_sym
|
50
|
+
@weights[str_or_sym]
|
51
51
|
end
|
52
52
|
|
53
53
|
# Get settings for this bundle.
|
54
54
|
#
|
55
55
|
# Returns an object.
|
56
56
|
#
|
57
|
-
def []
|
58
|
-
@configuration[
|
57
|
+
def [] str_or_sym
|
58
|
+
@configuration[str_or_sym]
|
59
59
|
end
|
60
60
|
|
61
61
|
# Loads all indexes.
|
@@ -63,38 +63,38 @@ module Picky
|
|
63
63
|
# Loading loads index objects from the backend.
|
64
64
|
# They should each respond to [] and return something appropriate.
|
65
65
|
#
|
66
|
-
def load
|
67
|
-
load_inverted
|
68
|
-
load_weights
|
69
|
-
load_similarity
|
66
|
+
def load symbol_keys = false
|
67
|
+
load_inverted symbol_keys
|
68
|
+
load_weights symbol_keys
|
69
|
+
load_similarity symbol_keys
|
70
70
|
load_configuration
|
71
71
|
load_realtime
|
72
72
|
end
|
73
73
|
|
74
74
|
# Loads the core index.
|
75
75
|
#
|
76
|
-
def load_inverted
|
77
|
-
self.inverted = @backend_inverted.load
|
76
|
+
def load_inverted symbol_keys
|
77
|
+
self.inverted = @backend_inverted.load symbol_keys
|
78
78
|
end
|
79
79
|
# Loads the weights index.
|
80
80
|
#
|
81
|
-
def load_weights
|
82
|
-
self.weights = @backend_weights.load unless @weight_strategy.respond_to?(:saved?) && !@weight_strategy.saved?
|
81
|
+
def load_weights symbol_keys
|
82
|
+
self.weights = @backend_weights.load symbol_keys unless @weight_strategy.respond_to?(:saved?) && !@weight_strategy.saved?
|
83
83
|
end
|
84
84
|
# Loads the similarity index.
|
85
85
|
#
|
86
|
-
def load_similarity
|
87
|
-
self.similarity = @backend_similarity.load unless @similarity_strategy.respond_to?(:saved?) && !@similarity_strategy.saved?
|
86
|
+
def load_similarity symbol_keys
|
87
|
+
self.similarity = @backend_similarity.load symbol_keys unless @similarity_strategy.respond_to?(:saved?) && !@similarity_strategy.saved?
|
88
88
|
end
|
89
89
|
# Loads the configuration.
|
90
90
|
#
|
91
91
|
def load_configuration
|
92
|
-
self.configuration = @backend_configuration.load
|
92
|
+
self.configuration = @backend_configuration.load false
|
93
93
|
end
|
94
94
|
# Loads the realtime mapping.
|
95
95
|
#
|
96
96
|
def load_realtime
|
97
|
-
self.realtime = @backend_realtime.load
|
97
|
+
self.realtime = @backend_realtime.load false
|
98
98
|
end
|
99
99
|
|
100
100
|
# Clears all indexes.
|
@@ -9,6 +9,8 @@ module Picky
|
|
9
9
|
|
10
10
|
# Removes the given id from the indexes.
|
11
11
|
#
|
12
|
+
# TODO Simplify (and slow) this again – remove the realtime index.
|
13
|
+
#
|
12
14
|
def remove id
|
13
15
|
# Is it anywhere?
|
14
16
|
#
|
@@ -46,13 +48,28 @@ module Picky
|
|
46
48
|
#
|
47
49
|
# Does not add to realtime if static.
|
48
50
|
#
|
51
|
+
# TODO What does static do again?
|
52
|
+
# TODO Why the realtime index? Is it really necessary?
|
53
|
+
# Not absolutely. It was for efficient deletion/replacement.
|
54
|
+
#
|
49
55
|
def add id, str_or_sym, method: :unshift, static: false, force_update: false
|
50
56
|
# If static, indexing will be slower, but will use less
|
51
57
|
# space in the end.
|
52
58
|
#
|
53
59
|
if static
|
54
60
|
ids = @inverted[str_or_sym] ||= []
|
55
|
-
|
61
|
+
if force_update
|
62
|
+
ids.delete id
|
63
|
+
ids.send method, id
|
64
|
+
else
|
65
|
+
# TODO Adding should not change the array if it's already in.
|
66
|
+
#
|
67
|
+
if ids.include?(id)
|
68
|
+
# Do nothing. Not forced, and already in.
|
69
|
+
else
|
70
|
+
ids.send method, id
|
71
|
+
end
|
72
|
+
end
|
56
73
|
else
|
57
74
|
# Use a generalized strategy.
|
58
75
|
#
|
@@ -60,19 +77,19 @@ module Picky
|
|
60
77
|
|
61
78
|
# Inverted.
|
62
79
|
#
|
63
|
-
ids = if str_or_syms
|
80
|
+
ids = if str_or_syms.include?(str_or_sym)
|
64
81
|
ids = @inverted[str_or_sym] ||= []
|
65
|
-
# If updates are
|
66
|
-
#
|
67
|
-
|
68
|
-
|
82
|
+
# If updates are forced or if it isn't in there already
|
83
|
+
# then remove and add to the index.
|
84
|
+
if force_update || !ids.include?(id)
|
85
|
+
ids.delete id
|
86
|
+
ids.send method, id
|
69
87
|
end
|
70
|
-
ids
|
71
|
-
ids.send method, id
|
88
|
+
ids
|
72
89
|
else
|
73
90
|
# Update the realtime index.
|
74
91
|
#
|
75
|
-
str_or_syms << str_or_sym
|
92
|
+
str_or_syms << str_or_sym
|
76
93
|
# TODO Add has_key? to index backends.
|
77
94
|
# ids = if @inverted.has_key?(str_or_sym)
|
78
95
|
# @inverted[str_or_sym]
|
@@ -129,11 +146,12 @@ module Picky
|
|
129
146
|
#
|
130
147
|
# THINK Maybe load it and just replace the arrays with the corresponding ones.
|
131
148
|
#
|
132
|
-
def build_realtime
|
149
|
+
def build_realtime symbol_keys
|
133
150
|
clear_realtime
|
134
151
|
@inverted.each_pair do |str_or_sym, ids|
|
135
152
|
ids.each do |id|
|
136
|
-
str_or_syms = @realtime[id] ||= []
|
153
|
+
str_or_syms = (@realtime[id] ||= [])
|
154
|
+
str_or_sym = str_or_sym.to_sym if symbol_keys
|
137
155
|
@realtime[id] << str_or_sym unless str_or_syms.include? str_or_sym
|
138
156
|
end
|
139
157
|
end
|
@@ -9,8 +9,8 @@ module Picky
|
|
9
9
|
def load
|
10
10
|
Picky.logger.load self
|
11
11
|
clear_realtime # THINK Should we really explicitly clear the realtime? Or should it just be loaded?
|
12
|
-
exact.load
|
13
|
-
partial.load
|
12
|
+
exact.load @symbol_keys
|
13
|
+
partial.load @symbol_keys
|
14
14
|
end
|
15
15
|
|
16
16
|
# Gets the weight for this token's text.
|
@@ -21,14 +21,14 @@ 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 str_or_sym(text)
|
25
25
|
weight && (weight + (sum || 0)) || sum
|
26
26
|
end
|
27
27
|
else
|
28
28
|
if tokenizer && tokenizer.stemmer?
|
29
|
-
bundle.weight token.stem(tokenizer)
|
29
|
+
bundle.weight str_or_sym(token.stem(tokenizer))
|
30
30
|
else
|
31
|
-
bundle.weight token.text
|
31
|
+
bundle.weight str_or_sym(token.text)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -45,18 +45,33 @@ module Picky
|
|
45
45
|
# It is 30% faster using the empty check
|
46
46
|
# than just << [].
|
47
47
|
#
|
48
|
-
ids = bundle.ids text
|
48
|
+
ids = bundle.ids str_or_sym(text)
|
49
49
|
ids.empty? ? result : result << ids
|
50
50
|
end.flatten
|
51
51
|
else
|
52
52
|
# Optimization
|
53
53
|
if tokenizer && tokenizer.stemmer?
|
54
|
-
bundle.ids token.stem(tokenizer)
|
54
|
+
bundle.ids str_or_sym(token.stem(tokenizer))
|
55
55
|
else
|
56
|
-
bundle.ids token.text
|
56
|
+
bundle.ids str_or_sym(token.text)
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
60
|
+
|
61
|
+
# Gets the similars for this token's text.
|
62
|
+
#
|
63
|
+
def similar token
|
64
|
+
bundle = bundle_for token
|
65
|
+
bundle.similar str_or_sym(token.text)
|
66
|
+
end
|
67
|
+
|
68
|
+
def str_or_sym text
|
69
|
+
if @symbol_keys
|
70
|
+
text.to_sym
|
71
|
+
else
|
72
|
+
text
|
73
|
+
end
|
74
|
+
end
|
60
75
|
|
61
76
|
# Returns the right index bundle for this token.
|
62
77
|
#
|
@@ -30,6 +30,8 @@ module Picky
|
|
30
30
|
# Removes the object's id, and then
|
31
31
|
# adds it again.
|
32
32
|
#
|
33
|
+
# TODO Is this the actual forced update?
|
34
|
+
#
|
33
35
|
def replace object, method: :unshift
|
34
36
|
remove object.send id
|
35
37
|
add object, method: method
|
@@ -74,8 +76,9 @@ module Picky
|
|
74
76
|
end
|
75
77
|
|
76
78
|
format = key_format?
|
79
|
+
static = static?
|
77
80
|
tokens.each do |text|
|
78
|
-
add_tokenized_token id, text, method: method, format: format, force_update: force_update
|
81
|
+
add_tokenized_token id, text, method: method, format: format, static: static, force_update: force_update
|
79
82
|
end
|
80
83
|
rescue NoMethodError => e
|
81
84
|
show_informative_add_text_error_message_for e
|
@@ -115,8 +118,8 @@ module Picky
|
|
115
118
|
# Builds the realtime mapping.
|
116
119
|
#
|
117
120
|
def build_realtime_mapping
|
118
|
-
exact.build_realtime
|
119
|
-
partial.build_realtime
|
121
|
+
exact.build_realtime @symbol_keys
|
122
|
+
partial.build_realtime @symbol_keys
|
120
123
|
end
|
121
124
|
|
122
125
|
end
|
data/lib/picky/query/token.rb
CHANGED
@@ -281,7 +281,7 @@ module Picky
|
|
281
281
|
# Returns all similar tokens for the token.
|
282
282
|
#
|
283
283
|
def similar_tokens_for category
|
284
|
-
similars = category.
|
284
|
+
similars = category.similar self
|
285
285
|
similars.map do |similar|
|
286
286
|
# The array describes all possible categories. There is only one here.
|
287
287
|
#
|
@@ -293,6 +293,7 @@ module Picky
|
|
293
293
|
#
|
294
294
|
@@qualifier_text_delimiter = /:/
|
295
295
|
@@qualifiers_delimiter = /,/
|
296
|
+
# TODO Think about making these instances.
|
296
297
|
@@qualifier_text_splitter = Splitter.new @@qualifier_text_delimiter
|
297
298
|
@@qualifiers_splitter = Splitter.new @@qualifiers_delimiter
|
298
299
|
def qualify
|
@@ -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
|
-
'
|
178
|
-
'
|
177
|
+
'kunz',
|
178
|
+
'hanke'
|
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
|
-
'
|
184
|
-
'
|
183
|
+
'kunz',
|
184
|
+
'hanke'
|
185
185
|
]
|
186
186
|
end
|
187
187
|
it 'has 0 facets >= counts 2' do
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe "Memory Usage" do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
Picky::Indexes.clear_indexes
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:thing) { Struct.new(:id, :text) }
|
12
|
+
|
13
|
+
# it 'is fine in String mode' do
|
14
|
+
# index = Picky::Index.new :memory_usage do
|
15
|
+
# category :text
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# require 'objspace'
|
19
|
+
#
|
20
|
+
# GC.start
|
21
|
+
# memsize_without_added_thing = ObjectSpace.memsize_of_all(String)
|
22
|
+
# GC.start
|
23
|
+
#
|
24
|
+
# index.add thing.new(1, 'one')
|
25
|
+
#
|
26
|
+
# GC.start
|
27
|
+
# memsize_with_added_thing = ObjectSpace.memsize_of_all(String)
|
28
|
+
# GC.start
|
29
|
+
#
|
30
|
+
# index.add thing.new(1, 'one')
|
31
|
+
#
|
32
|
+
# GC.start
|
33
|
+
# memsize_with_readded_thing = ObjectSpace.memsize_of_all(String)
|
34
|
+
# GC.start
|
35
|
+
#
|
36
|
+
# memsize_with_readded_thing.should == memsize_with_added_thing
|
37
|
+
# end
|
38
|
+
|
39
|
+
it 'is fine with Symbols' do
|
40
|
+
index = Picky::Index.new :memory_usage do
|
41
|
+
symbol_keys true
|
42
|
+
|
43
|
+
category :text
|
44
|
+
end
|
45
|
+
|
46
|
+
require 'objspace'
|
47
|
+
|
48
|
+
GC.start
|
49
|
+
memsize_without_added_thing = ObjectSpace.memsize_of_all(Symbol)
|
50
|
+
GC.start
|
51
|
+
|
52
|
+
index.add thing.new(1, 'one')
|
53
|
+
|
54
|
+
GC.start
|
55
|
+
memsize_with_added_thing = ObjectSpace.memsize_of_all(Symbol)
|
56
|
+
GC.start
|
57
|
+
|
58
|
+
index.add thing.new(1, 'one')
|
59
|
+
|
60
|
+
GC.start
|
61
|
+
memsize_with_readded_thing = ObjectSpace.memsize_of_all(Symbol)
|
62
|
+
GC.start
|
63
|
+
|
64
|
+
memsize_with_readded_thing.should == memsize_with_added_thing
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -6,33 +6,66 @@ require 'spec_helper'
|
|
6
6
|
# already in the index.
|
7
7
|
#
|
8
8
|
describe 'ignoring updates' do
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
|
10
|
+
normal_index = Picky::Index.new :normal do
|
11
|
+
category :title
|
12
|
+
end
|
13
|
+
|
14
|
+
symbol_keys_index = Picky::Index.new :symbol do
|
15
|
+
symbol_keys
|
16
|
+
|
17
|
+
category :title
|
18
|
+
end
|
19
|
+
|
20
|
+
static_index = Picky::Index.new :static do
|
21
|
+
static
|
22
|
+
|
23
|
+
category :title
|
24
|
+
end
|
25
|
+
|
26
|
+
[normal_index, symbol_keys_index, static_index].each do |index|
|
27
|
+
it 'does not update the index if the added data stayed the same' do
|
28
|
+
thing = Struct.new :id, :title
|
29
|
+
index.add thing.new(1, 'some title')
|
30
|
+
index.add thing.new(2, 'some title')
|
18
31
|
|
19
|
-
|
32
|
+
try = Picky::Search.new index
|
20
33
|
|
21
|
-
|
34
|
+
try.search('some').ids.should == [2, 1]
|
22
35
|
|
23
|
-
|
36
|
+
index.add thing.new(1, 'some title'), force_update: true
|
24
37
|
|
25
|
-
|
26
|
-
|
38
|
+
# Expected behavior.
|
39
|
+
try.search('some').ids.should == [1, 2]
|
27
40
|
|
28
|
-
|
41
|
+
index.add thing.new(2, 'some title') # force_update: false is the default.
|
29
42
|
|
30
|
-
|
31
|
-
|
43
|
+
# Not updated, since it was the exact same data everywhere.
|
44
|
+
try.search('some').ids.should == [1, 2]
|
32
45
|
|
33
|
-
|
46
|
+
index.add thing.new(2, 'some title'), force_update: false
|
34
47
|
|
35
|
-
|
36
|
-
|
48
|
+
# Not updated, since it was the exact same data everywhere.
|
49
|
+
try.search('some').ids.should == [1, 2]
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'does always update the index if replace is used' do
|
53
|
+
index = Picky::Index.new :books do
|
54
|
+
category :title
|
55
|
+
end
|
56
|
+
|
57
|
+
thing = Struct.new :id, :title
|
58
|
+
index.add thing.new(1, 'some title')
|
59
|
+
index.add thing.new(2, 'some title')
|
60
|
+
|
61
|
+
try = Picky::Search.new index
|
62
|
+
|
63
|
+
try.search('some').ids.should == [2, 1]
|
64
|
+
|
65
|
+
index.replace thing.new(1, 'some title')
|
66
|
+
|
67
|
+
# Expected behavior.
|
68
|
+
try.search('some').ids.should == [1, 2]
|
69
|
+
end
|
37
70
|
end
|
38
71
|
end
|
@@ -11,241 +11,249 @@ describe "Realtime Indexing" do
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
14
|
+
default_index = Picky::Index.new(:books) do
|
15
|
+
category :title
|
16
|
+
category :author, similarity: Picky::Generators::Similarity::DoubleMetaphone.new(3)
|
17
|
+
end
|
18
|
+
|
19
|
+
symbol_keys_index = Picky::Index.new(:books) do
|
20
|
+
symbol_keys true
|
21
|
+
|
22
|
+
category :title
|
23
|
+
category :author, similarity: Picky::Generators::Similarity::DoubleMetaphone.new(3)
|
24
|
+
end
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
[symbol_keys_index].each do |index|
|
27
|
+
context 'default index' do
|
28
|
+
before(:each) { index.clear }
|
29
|
+
let(:books) { Picky::Search.new index }
|
27
30
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
+
before(:each) do
|
32
|
+
index.add Book.new(1, "Title", "Author")
|
33
|
+
end
|
31
34
|
|
32
|
-
|
35
|
+
context 'dumping and loading' do
|
36
|
+
it "doesn't find books anymore after dumping and loading and updating" do
|
37
|
+
index.replace Book.new(2, "Title New", "Author New")
|
33
38
|
|
34
|
-
|
35
|
-
index.load
|
36
|
-
index.build_realtime_mapping
|
39
|
+
books.search("title").ids.should == [2, 1]
|
37
40
|
|
38
|
-
|
41
|
+
index.dump
|
42
|
+
index.load
|
43
|
+
index.build_realtime_mapping
|
39
44
|
|
40
|
-
|
41
|
-
end
|
42
|
-
end
|
45
|
+
index.replace Book.new(2, "Blah New", "Author New")
|
43
46
|
|
44
|
-
|
45
|
-
|
46
|
-
books.search('title:Titl').ids.should == [1]
|
47
|
+
books.search("title").ids.should == [1]
|
48
|
+
end
|
47
49
|
end
|
48
50
|
|
49
|
-
|
50
|
-
|
51
|
+
context 'single category updating' do
|
52
|
+
it 'finds the first entry' do
|
53
|
+
books.search('title:Titl').ids.should == [1]
|
54
|
+
end
|
51
55
|
|
52
|
-
|
53
|
-
|
54
|
-
end
|
56
|
+
it 'allows removing a single category and leaving the others alone' do
|
57
|
+
index[:title].remove 1
|
55
58
|
|
56
|
-
|
57
|
-
|
59
|
+
books.search('Title').ids.should == []
|
60
|
+
books.search('Author').ids.should == [1]
|
61
|
+
end
|
58
62
|
|
59
|
-
|
60
|
-
|
63
|
+
it 'allows adding a single category and leaving the others alone' do
|
64
|
+
index[:title].add Book.new(2, "Newtitle", "Newauthor")
|
61
65
|
|
62
|
-
|
63
|
-
|
64
|
-
end
|
66
|
+
books.search('Title').ids.should == [1]
|
67
|
+
books.search('Newtitle').ids.should == [2]
|
65
68
|
|
66
|
-
|
67
|
-
|
69
|
+
books.search('Author').ids.should == [1]
|
70
|
+
books.search('Newauthor').ids.should == []
|
71
|
+
end
|
68
72
|
|
69
|
-
|
70
|
-
|
73
|
+
it 'allows replacing a single category and leaving the others alone' do
|
74
|
+
index[:title].replace Book.new(1, "Replaced", "Notindexed")
|
71
75
|
|
72
|
-
|
73
|
-
|
74
|
-
end
|
75
|
-
end
|
76
|
+
books.search('Title').ids.should == []
|
77
|
+
books.search('Replaced').ids.should == [1]
|
76
78
|
|
77
|
-
|
78
|
-
|
79
|
-
|
79
|
+
books.search('Notindexed').ids.should == []
|
80
|
+
books.search('Author').ids.should == [1]
|
81
|
+
end
|
80
82
|
end
|
81
83
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
books.search('Titl').ids.should == [1]
|
84
|
+
context 'with partial' do
|
85
|
+
it 'finds the first entry' do
|
86
|
+
books.search('Titl').ids.should == [1]
|
87
|
+
end
|
87
88
|
|
88
|
-
|
89
|
+
it 'allows removing something' do
|
90
|
+
index.remove 1
|
91
|
+
end
|
92
|
+
it 'is not findable anymore after removing' do
|
93
|
+
books.search('Titl').ids.should == [1]
|
89
94
|
|
90
|
-
|
91
|
-
end
|
95
|
+
index.remove 1
|
92
96
|
|
93
|
-
|
94
|
-
|
95
|
-
end
|
96
|
-
it 'is findable after adding' do
|
97
|
-
books.search('Titl').ids.should == [1]
|
97
|
+
books.search('Titl').ids.should == []
|
98
|
+
end
|
98
99
|
|
99
|
-
|
100
|
+
it 'allows adding something' do
|
101
|
+
index.add Book.new(2, "Title2", "Author2")
|
102
|
+
end
|
103
|
+
it 'is findable after adding' do
|
104
|
+
books.search('Titl').ids.should == [1]
|
100
105
|
|
101
|
-
|
102
|
-
end
|
106
|
+
index.add Book.new(2, "Title New", "Author New")
|
103
107
|
|
104
|
-
|
105
|
-
|
106
|
-
end
|
107
|
-
it 'is findable after replacing' do
|
108
|
-
books.search('Ne').ids.should == []
|
108
|
+
books.search('Titl').ids.should == [2,1]
|
109
|
+
end
|
109
110
|
|
110
|
-
|
111
|
+
it 'allows replacing something' do
|
112
|
+
index.replace Book.new(1, "Title New", "Author New")
|
113
|
+
end
|
114
|
+
it 'is findable after replacing' do
|
115
|
+
books.search('Ne').ids.should == []
|
111
116
|
|
112
|
-
|
113
|
-
end
|
114
|
-
it 'handles more complex cases' do
|
115
|
-
books.search('Ne').ids.should == []
|
117
|
+
index.replace Book.new(1, "Title New", "Author New")
|
116
118
|
|
117
|
-
|
119
|
+
books.search('Ne').ids.should == [1, 1]
|
120
|
+
end
|
121
|
+
it 'handles more complex cases' do
|
122
|
+
books.search('Ne').ids.should == []
|
118
123
|
|
119
|
-
|
120
|
-
end
|
121
|
-
it 'handles more complex cases' do
|
122
|
-
index.remove 1
|
124
|
+
index.replace Book.new(1, "Title New", "Author New")
|
123
125
|
|
124
|
-
|
126
|
+
books.search('title:Ne').ids.should == [1]
|
127
|
+
end
|
128
|
+
it 'handles more complex cases' do
|
129
|
+
index.remove 1
|
125
130
|
|
126
|
-
|
131
|
+
books.search('Titl').ids.should == []
|
127
132
|
|
128
|
-
|
129
|
-
end
|
130
|
-
end
|
133
|
+
index.replace Book.new(1, "Title New", "Author New")
|
131
134
|
|
132
|
-
|
133
|
-
|
134
|
-
books.search('Titl').ids.should == [1]
|
135
|
+
books.search('title:Ne').ids.should == [1]
|
136
|
+
end
|
135
137
|
end
|
136
138
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
books.search('Titl').ids.should == [1]
|
139
|
+
context 'non-partial' do
|
140
|
+
it 'finds the first entry' do
|
141
|
+
books.search('Titl').ids.should == [1]
|
142
|
+
end
|
142
143
|
|
143
|
-
|
144
|
+
it 'allows removing something' do
|
145
|
+
index.remove 1
|
146
|
+
end
|
147
|
+
it 'is not findable anymore after removing' do
|
148
|
+
books.search('Titl').ids.should == [1]
|
144
149
|
|
145
|
-
|
146
|
-
end
|
150
|
+
index.remove 1
|
147
151
|
|
148
|
-
|
149
|
-
|
150
|
-
end
|
151
|
-
it 'is findable after adding' do
|
152
|
-
books.search('Titl').ids.should == [1]
|
152
|
+
books.search('Titl').ids.should == []
|
153
|
+
end
|
153
154
|
|
154
|
-
|
155
|
+
it 'allows adding something' do
|
156
|
+
index.add Book.new(2, "Title2", "Author2")
|
157
|
+
end
|
158
|
+
it 'is findable after adding' do
|
159
|
+
books.search('Titl').ids.should == [1]
|
155
160
|
|
156
|
-
|
157
|
-
end
|
161
|
+
index.add Book.new(2, "Title New", "Author New")
|
158
162
|
|
159
|
-
|
160
|
-
|
161
|
-
end
|
162
|
-
it 'is findable after replacing' do
|
163
|
-
books.search('Ne').ids.should == []
|
163
|
+
books.search('Titl').ids.should == [2,1]
|
164
|
+
end
|
164
165
|
|
165
|
-
|
166
|
+
it 'allows replacing something' do
|
167
|
+
index.replace Book.new(1, "Title New", "Author New")
|
168
|
+
end
|
169
|
+
it 'is findable after replacing' do
|
170
|
+
books.search('Ne').ids.should == []
|
166
171
|
|
167
|
-
|
168
|
-
end
|
169
|
-
it 'handles more complex cases' do
|
170
|
-
books.search('Ne').ids.should == []
|
172
|
+
index.replace Book.new(1, "Title New", "Author New")
|
171
173
|
|
172
|
-
|
174
|
+
books.search('Ne').ids.should == [1, 1]
|
175
|
+
end
|
176
|
+
it 'handles more complex cases' do
|
177
|
+
books.search('Ne').ids.should == []
|
173
178
|
|
174
|
-
|
175
|
-
end
|
176
|
-
it 'handles more complex cases' do
|
177
|
-
index.remove 1
|
179
|
+
index.replace Book.new(1, "Title New", "Author New")
|
178
180
|
|
179
|
-
|
181
|
+
books.search('title:Ne').ids.should == [1]
|
182
|
+
end
|
183
|
+
it 'handles more complex cases' do
|
184
|
+
index.remove 1
|
180
185
|
|
181
|
-
|
186
|
+
books.search('Titl').ids.should == []
|
182
187
|
|
183
|
-
|
184
|
-
end
|
185
|
-
end
|
188
|
+
index.replace Book.new(1, "Title New", "Author New")
|
186
189
|
|
187
|
-
|
188
|
-
|
189
|
-
books.search('Authr~').ids.should == [1]
|
190
|
+
books.search('title:Ne').ids.should == [1]
|
191
|
+
end
|
190
192
|
end
|
191
193
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
books.search('Authr~').ids.should == [1]
|
194
|
+
context 'similarity' do
|
195
|
+
it 'finds the first entry' do
|
196
|
+
books.search('Authr~').ids.should == [1]
|
197
|
+
end
|
197
198
|
|
198
|
-
|
199
|
+
it 'allows removing something' do
|
200
|
+
index.remove 1
|
201
|
+
end
|
202
|
+
it 'is not findable anymore after removing' do
|
203
|
+
books.search('Authr~').ids.should == [1]
|
199
204
|
|
200
|
-
|
201
|
-
end
|
205
|
+
index.remove 1
|
202
206
|
|
203
|
-
|
204
|
-
|
205
|
-
end
|
206
|
-
it 'is findable after adding' do
|
207
|
-
books.search('Authr~').ids.should == [1]
|
207
|
+
books.search('Authr~').ids.should == []
|
208
|
+
end
|
208
209
|
|
209
|
-
|
210
|
+
it 'allows adding something' do
|
211
|
+
index.add Book.new(2, "Title2", "Author2")
|
212
|
+
end
|
213
|
+
it 'is findable after adding' do
|
214
|
+
books.search('Authr~').ids.should == [1]
|
210
215
|
|
211
|
-
|
212
|
-
end
|
216
|
+
index.add Book.new(2, "Title New", "Author New")
|
213
217
|
|
214
|
-
|
215
|
-
|
216
|
-
end
|
217
|
-
it 'is findable after replacing' do
|
218
|
-
books.search('Nuw~').ids.should == []
|
218
|
+
books.search('Authr~').ids.should == [2,1]
|
219
|
+
end
|
219
220
|
|
220
|
-
|
221
|
+
it 'allows replacing something' do
|
222
|
+
index.replace Book.new(1, "Title New", "Author New")
|
223
|
+
end
|
224
|
+
it 'is findable after replacing' do
|
225
|
+
books.search('Nuw~').ids.should == []
|
221
226
|
|
222
|
-
|
223
|
-
end
|
224
|
-
it 'handles more complex cases' do
|
225
|
-
books.search('Now~').ids.should == []
|
227
|
+
index.replace Book.new(1, "Title New", "Author New")
|
226
228
|
|
227
|
-
|
229
|
+
books.search('Nuw~').ids.should == [1]
|
230
|
+
end
|
231
|
+
it 'handles more complex cases' do
|
232
|
+
books.search('Now~').ids.should == []
|
228
233
|
|
229
|
-
|
230
|
-
end
|
231
|
-
it 'handles more complex cases' do
|
232
|
-
index.remove 1
|
234
|
+
index.replace Book.new(1, "Title New", "Author New")
|
233
235
|
|
234
|
-
|
236
|
+
books.search('author:Now~').ids.should == [1]
|
237
|
+
end
|
238
|
+
it 'handles more complex cases' do
|
239
|
+
index.remove 1
|
235
240
|
|
236
|
-
|
241
|
+
books.search('Athr~').ids.should == []
|
237
242
|
|
238
|
-
|
239
|
-
end
|
240
|
-
it 'handles more complex cases' do
|
241
|
-
books.search('Athr~').ids.should == [1]
|
243
|
+
index.replace Book.new(1, "Title New", "Author New")
|
242
244
|
|
243
|
-
|
244
|
-
|
245
|
+
books.search('author:Athr~').ids.should == [1]
|
246
|
+
end
|
247
|
+
it 'handles more complex cases' do
|
248
|
+
books.search('Athr~').ids.should == [1]
|
245
249
|
|
246
|
-
|
247
|
-
|
248
|
-
|
250
|
+
index.replace Book.new(2, "Title New", "Author New")
|
251
|
+
index.add Book.new(3, "TTL", "AUTHR")
|
252
|
+
|
253
|
+
# Note: [2, 1] are in one allocation, [3] in the other.
|
254
|
+
#
|
255
|
+
books.search('author:Athr~').ids.should == [2, 1, 3]
|
256
|
+
end
|
249
257
|
end
|
250
258
|
end
|
251
259
|
end
|
@@ -24,7 +24,7 @@ describe "static option" do
|
|
24
24
|
try.search("text:ohai").ids.should == [1, 2]
|
25
25
|
end
|
26
26
|
|
27
|
-
it '
|
27
|
+
it 'does not add to the realtime index' do
|
28
28
|
index = Picky::Index.new :static do
|
29
29
|
static
|
30
30
|
|
@@ -34,7 +34,7 @@ describe "static option" do
|
|
34
34
|
index.add OpenStruct.new id: 1, text: "ohai"
|
35
35
|
index.add OpenStruct.new id: 2, text: "ohai kthxbye"
|
36
36
|
|
37
|
-
index[:text].exact.realtime.should == {
|
37
|
+
index[:text].exact.realtime.should == {}
|
38
38
|
|
39
39
|
try = Picky::Search.new index
|
40
40
|
try.search("text:ohai").ids.should == [2, 1]
|
@@ -46,7 +46,7 @@ describe Picky::Backends::SQLite::Array do
|
|
46
46
|
|
47
47
|
describe 'load' do
|
48
48
|
it 'returns a copy of itself' do
|
49
|
-
db.load.should == db
|
49
|
+
db.load(:anything).should == db
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -111,7 +111,7 @@ describe Picky::Backends::SQLite::Array do
|
|
111
111
|
|
112
112
|
describe 'load' do
|
113
113
|
it 'returns a copy of itself' do
|
114
|
-
db.load.should == db
|
114
|
+
db.load(:anything).should == db
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
@@ -106,12 +106,12 @@ describe Picky::Bundle do
|
|
106
106
|
@bundle.dump # Create an index first.
|
107
107
|
end
|
108
108
|
it 'should trigger loads' do
|
109
|
-
@bundle.should_receive(:load_inverted).once.with
|
110
|
-
@bundle.should_receive(:load_weights).once.with
|
111
|
-
@bundle.should_receive(:load_similarity).once.with
|
109
|
+
@bundle.should_receive(:load_inverted).once.with :something
|
110
|
+
@bundle.should_receive(:load_weights).once.with :something
|
111
|
+
@bundle.should_receive(:load_similarity).once.with :something
|
112
112
|
@bundle.should_receive(:load_configuration).once.with no_args
|
113
113
|
|
114
|
-
@bundle.load
|
114
|
+
@bundle.load :something
|
115
115
|
end
|
116
116
|
end
|
117
117
|
describe "loading indexes" do
|
@@ -124,7 +124,7 @@ describe Picky::Bundle do
|
|
124
124
|
|
125
125
|
File.should_receive(:open).once.with 'spec/temp/index/test/some_index/some_category_some_name_inverted.memory.json', 'r'
|
126
126
|
|
127
|
-
@bundle.load_inverted
|
127
|
+
@bundle.load_inverted :anything
|
128
128
|
end
|
129
129
|
end
|
130
130
|
describe "load_weights" do
|
@@ -133,7 +133,7 @@ describe Picky::Bundle do
|
|
133
133
|
|
134
134
|
File.should_receive(:open).once.with 'spec/temp/index/test/some_index/some_category_some_name_weights.memory.json', 'r'
|
135
135
|
|
136
|
-
@bundle.load_weights
|
136
|
+
@bundle.load_weights :anything
|
137
137
|
end
|
138
138
|
end
|
139
139
|
describe "load_similarity" do
|
@@ -142,7 +142,7 @@ describe Picky::Bundle do
|
|
142
142
|
|
143
143
|
File.should_receive(:open).once.with 'spec/temp/index/test/some_index/some_category_some_name_similarity.memory.dump', 'r:binary'
|
144
144
|
|
145
|
-
@bundle.load_similarity
|
145
|
+
@bundle.load_similarity :anything
|
146
146
|
end
|
147
147
|
end
|
148
148
|
describe "load_configuration" do
|
@@ -75,8 +75,7 @@ describe Picky::Query::Token do
|
|
75
75
|
let(:token) { described_class.processed 'similar~', 'Similar~' }
|
76
76
|
context 'with similar' do
|
77
77
|
before(:each) do
|
78
|
-
@
|
79
|
-
@category = double :category, :bundle_for => @bundle
|
78
|
+
@category = double :category, :similar => ['array', 'of', 'similar']
|
80
79
|
end
|
81
80
|
it 'returns a list of tokens' do
|
82
81
|
token.similar_tokens_for(@category).each do |token|
|
@@ -102,8 +101,7 @@ describe Picky::Query::Token do
|
|
102
101
|
end
|
103
102
|
context 'without similar' do
|
104
103
|
before(:each) do
|
105
|
-
@
|
106
|
-
@category = double :category, :bundle_for => @bundle
|
104
|
+
@category = double :category, :similar => []
|
107
105
|
end
|
108
106
|
it 'returns an empty list' do
|
109
107
|
token.similar_tokens_for(@category).should == []
|
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.
|
4
|
+
version: 4.31.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Hanke
|
@@ -238,6 +238,7 @@ files:
|
|
238
238
|
- spec/functional/ignore_spec.rb
|
239
239
|
- spec/functional/max_allocations_spec.rb
|
240
240
|
- spec/functional/memory_leak_spec.rb
|
241
|
+
- spec/functional/memory_usage_spec.rb
|
241
242
|
- spec/functional/multi_index_qualifier_spec.rb
|
242
243
|
- spec/functional/no_dump_hint_spec.rb
|
243
244
|
- spec/functional/no_tokenize_spec.rb
|
@@ -396,7 +397,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
396
397
|
version: '0'
|
397
398
|
requirements: []
|
398
399
|
rubyforge_project: http://rubyforge.org/projects/picky
|
399
|
-
rubygems_version: 2.4.
|
400
|
+
rubygems_version: 2.4.5
|
400
401
|
signing_key:
|
401
402
|
specification_version: 4
|
402
403
|
summary: 'Picky: Semantic Search Engine. Clever Interface. Good Tools.'
|
@@ -425,6 +426,7 @@ test_files:
|
|
425
426
|
- spec/functional/ignore_spec.rb
|
426
427
|
- spec/functional/max_allocations_spec.rb
|
427
428
|
- spec/functional/memory_leak_spec.rb
|
429
|
+
- spec/functional/memory_usage_spec.rb
|
428
430
|
- spec/functional/multi_index_qualifier_spec.rb
|
429
431
|
- spec/functional/no_dump_hint_spec.rb
|
430
432
|
- spec/functional/no_tokenize_spec.rb
|