-
Notifications
You must be signed in to change notification settings - Fork 49
/
bundle.rb
171 lines (150 loc) · 4.99 KB
/
bundle.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
module Picky
# A Bundle is a number of indexes
# per [index, category] combination.
#
# At most, there are three indexes:
# * *core* index (always used)
# * *weights* index (always used)
# * *similarity* index (used with similarity)
#
# In Picky, indexing is separated from the index
# handling itself through a parallel structure.
#
# Both use methods provided by this base class, but
# have very different goals:
#
# * *Indexing*::*Bundle*::*Base* is just concerned with creating index
# files / redis entries and providing helper functions to e.g. check
# the indexes.
#
# * *Index*::*Bundle*::*Base* is concerned with loading these index files into
# memory / redis and looking up search data as fast as possible.
#
class Bundle
attr_reader :name,
:category
attr_accessor :inverted,
:weights,
:similarity,
:configuration,
:realtime,
:backend_inverted,
:backend_weights,
:backend_similarity,
:backend_configuration,
:backend_realtime,
:weight_strategy,
:partial_strategy,
:similarity_strategy
delegate :[], :[]=, :to => :configuration
delegate :index_directory, :to => :category
# TODO Move the strategies into options.
#
def initialize name, category, weight_strategy, partial_strategy, similarity_strategy, options = {}
@name = name
@category = category
@weight_strategy = weight_strategy
@partial_strategy = partial_strategy
@similarity_strategy = similarity_strategy
@key_format = options.delete :key_format
@backend = options.delete :backend
reset_backend
end
def identifier
@identifier ||= :"#{category.identifier}:#{name}"
end
# If no specific backend has been set,
# uses the category's backend.
#
def backend
@backend || category.backend
end
# Initializes all necessary indexes from the backend.
#
def reset_backend
create_backends
initialize_backends
end
# Extract specific indexes from backend.
#
def create_backends
@backend_inverted = backend.create_inverted self
@backend_weights = backend.create_weights self
@backend_similarity = backend.create_similarity self
@backend_configuration = backend.create_configuration self
@backend_realtime = backend.create_realtime self
end
# Initial indexes.
#
# Note that if the weights strategy doesn't need to be saved,
# the strategy itself pretends to be an index.
#
def initialize_backends
on_all_indexes_call :initial
end
# "Empties" the index(es) by getting a new empty
# internal backend instance.
#
def empty
on_all_indexes_call :empty
end
# Extracted to avoid duplicate code.
#
def on_all_indexes_call method_name
@inverted = @backend_inverted.send method_name
@weights = @weight_strategy.respond_to?(:saved?) && !@weight_strategy.saved? ? @weight_strategy : @backend_weights.send(method_name)
@similarity = @backend_similarity.send method_name
@configuration = @backend_configuration.send method_name
@realtime = @backend_realtime.send method_name
end
# Delete all index files.
#
def delete
@backend_inverted.delete if @backend_inverted.respond_to? :delete
# THINK about this. Perhaps the strategies should implement the backend methods?
#
@backend_weights.delete if @backend_weights.respond_to?(:delete) && @weight_strategy.respond_to?(:saved?) && @weight_strategy.saved?
@backend_similarity.delete if @backend_similarity.respond_to? :delete
@backend_configuration.delete if @backend_configuration.respond_to? :delete
@backend_realtime.delete if @backend_realtime.respond_to? :delete
end
# Get a list of similar texts.
#
# Note: Does not return itself.
#
def similar text
code = similarity_strategy.encode text
return [] unless code
similar_codes = @similarity[code]
if similar_codes.blank?
[] # Return a simple array.
else
similar_codes = similar_codes.dup
similar_codes.delete text
similar_codes
end
end
# If a key format is set, use it, else delegate to the category.
#
def key_format
@key_format || @category.key_format
end
# Path and partial filename of a specific subindex.
#
# Subindexes are:
# * inverted index
# * weights index
# * partial index
# * similarity index
#
# Returns just the part without subindex type,
# if none given.
#
def index_path type = nil
::File.join index_directory, "#{category.name}_#{name}#{ "_#{type}" if type }"
end
def to_s
"#{self.class}(#{identifier})"
end
end
end