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