solrizer 2.2.0 → 3.0.0.pre1
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.
- data/.gitignore +1 -1
- data/History.txt +12 -0
- data/lib/solrizer/common.rb +3 -18
- data/lib/solrizer/default_descriptors.rb +93 -0
- data/lib/solrizer/descriptor.rb +68 -0
- data/lib/solrizer/field_mapper.rb +107 -288
- data/lib/solrizer/version.rb +1 -1
- data/lib/solrizer/xml/extractor.rb +5 -5
- data/lib/solrizer/xml/terminology_based_solrizer.rb +4 -20
- data/lib/solrizer.rb +1 -1
- data/solrizer.gemspec +1 -1
- data/spec/fixtures/mods_article.rb +0 -1
- data/spec/spec_helper.rb +0 -1
- data/spec/units/common_spec.rb +8 -12
- data/spec/units/extractor_spec.rb +3 -2
- data/spec/units/field_mapper_spec.rb +177 -141
- data/spec/units/xml_extractor_spec.rb +13 -14
- data/spec/units/xml_terminology_based_solrizer_spec.rb +13 -22
- metadata +56 -33
- checksums.yaml +0 -7
- data/lib/solrizer/field_name_mapper.rb +0 -51
- data/spec/units/field_name_mapper_spec.rb +0 -28
@@ -1,58 +1,41 @@
|
|
1
1
|
require "loggable"
|
2
|
-
require 'active_support'
|
2
|
+
require 'active_support/core_ext/class/attribute'
|
3
|
+
require 'active_support/core_ext/string/inflections'
|
3
4
|
module Solrizer
|
4
|
-
|
5
|
+
|
6
|
+
class SolrizerError < RuntimeError; end #nodoc#
|
7
|
+
class InvalidIndexDescriptor < SolrizerError; end #nodoc#
|
8
|
+
class UnknownIndexMacro < SolrizerError; end #nodoc#
|
5
9
|
# Maps Term names and values to Solr fields, based on the Term's data type and any index_as options.
|
6
10
|
#
|
7
11
|
# The basic structure of a mapper is:
|
8
12
|
#
|
9
13
|
# == Mapping on Index Type
|
10
14
|
#
|
11
|
-
# To
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# # t.dish_name :index_as => [:searchable] -maps to-> dish_name_search
|
19
|
-
# # t.ingredients :index_as => [:searchable, :edible] -maps to-> ingredients_search, ingredients_food
|
20
|
-
#
|
21
|
-
# (See Solrizer::XML::TerminologyBasedSolrizer for instructions on applying a custom mapping once you have defined it.)
|
22
|
-
#
|
23
|
-
# == Default Index Types
|
24
|
-
#
|
25
|
-
# You can mark a particular index type as a default. It will then always be included unless terms explicity
|
26
|
-
# exclude it with the "not_" prefix:
|
27
|
-
#
|
28
|
-
# class CustomMapper < Solrizer::FieldMapper
|
29
|
-
# index_as :searchable, :suffix => '_search', :default => true
|
30
|
-
# index_as :edible, :suffix => '_food'
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
# # t.dish_name -maps to-> dish_name_search
|
34
|
-
# # t.ingredients :index_as => [:edible] -maps to-> ingredients_search, ingredients_food
|
35
|
-
# # t.secret_ingredients :index_as => [:not_searchable, :edible] -maps to-> secret_ingredients_food
|
36
|
-
#
|
37
|
-
# == Mapping on Data Type
|
15
|
+
# To add a custom mapper to the default mapper
|
16
|
+
#
|
17
|
+
# module Solrizer::DefaultDescriptors
|
18
|
+
# def self.some_field_type
|
19
|
+
# @some_field_type ||= Descriptor.new(:string, :stored, :indexed, :multivalued)
|
20
|
+
# end
|
38
21
|
#
|
39
|
-
#
|
22
|
+
# # Or some totally different field:
|
23
|
+
# def self.edible
|
24
|
+
# @some_field_type ||= EdibleDescriptor.new()
|
25
|
+
# end
|
40
26
|
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
# type.float :suffix => '_numeric'
|
27
|
+
# class EdibleDescriptor < Solrizer::Descriptor
|
28
|
+
# def name_and_converter(field_name, field_type)
|
29
|
+
# [field_name + '_food']
|
30
|
+
# end
|
46
31
|
# end
|
47
|
-
# index_as :edible, :suffix => '_food'
|
48
32
|
# end
|
49
33
|
#
|
50
|
-
# # t.
|
51
|
-
# # t.
|
34
|
+
# # t.dish_name :index_as => [:some_field_type] -maps to-> dish_name_ssim
|
35
|
+
# # t.ingredients :index_as => [:some_field_type, :edible] -maps to-> ingredients_ssim, ingredients_food
|
52
36
|
#
|
53
|
-
#
|
37
|
+
# (See Solrizer::XML::TerminologyBasedSolrizer for instructions on applying a custom mapping once you have defined it.)
|
54
38
|
#
|
55
|
-
# # t.description :type => :text, :index_as => [:searchable] -maps to-> description_search
|
56
39
|
#
|
57
40
|
# == Custom Value Converters
|
58
41
|
#
|
@@ -60,185 +43,130 @@ module Solrizer
|
|
60
43
|
# generation of Solr values by attaching a custom value converter block to a data type:
|
61
44
|
#
|
62
45
|
# require 'time'
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
# type.date do |value|
|
67
|
-
# Time.parse(value).utc.to_i
|
68
|
-
# end
|
46
|
+
# module Solrizer::DefaultDescriptors
|
47
|
+
# def self.searchable
|
48
|
+
# @searchable ||= SearchableDescriptor.new(:string, :stored, :indexed, :multivalued, converter: my_converter)
|
69
49
|
# end
|
70
|
-
# end
|
71
|
-
#
|
72
|
-
# Note that the nesting order is always:
|
73
|
-
#
|
74
|
-
# FieldMapper definition
|
75
|
-
# index_as
|
76
|
-
# data type
|
77
|
-
# value converter
|
78
|
-
#
|
79
|
-
# You can use the special data type "default" to apply custom value conversion to any data type:
|
80
50
|
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
# value.to_s.strip
|
51
|
+
# def self.my_converter
|
52
|
+
# lambda do |type|
|
53
|
+
# case type
|
54
|
+
# when :date
|
55
|
+
# lambda { |value| Time.parse(value).utc.to_i }
|
56
|
+
# else
|
57
|
+
# lambda { |value| value.to_s.strip }
|
58
|
+
# end
|
90
59
|
# end
|
91
60
|
# end
|
92
61
|
# end
|
93
62
|
#
|
94
63
|
# This example converts searchable dates to milliseconds, and strips extra whitespace from all other searchable data types.
|
95
64
|
#
|
96
|
-
# Note that the :suffix option may appear on the data types and the index_as. The search order for the suffix on a field
|
97
|
-
# of type foo is:
|
98
|
-
# 1. type.foo
|
99
|
-
# 2. type.default
|
100
|
-
# 3. index_as
|
101
|
-
# The suffix is optional in all three places.
|
102
|
-
#
|
103
|
-
# Note that a single Term with multiple index types can translate into multiple Solr fields, because we may want Solr to
|
104
|
-
# index a single field in multiple ways. However, if two different mappings generate both the same solr field name
|
105
|
-
# _and_ the same value, the mapper will only emit a single field.
|
106
65
|
#
|
107
66
|
# == ID Field
|
108
67
|
#
|
109
68
|
# In addition to the normal field mappings, Solrizer gives special treatment to an ID field. If you want that
|
110
69
|
# logic (and you probably do), specify a name for this field:
|
111
70
|
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
# end
|
71
|
+
# Solrizer::FieldMapper.id_field = 'id'
|
72
|
+
#
|
115
73
|
#
|
116
74
|
# == Extending the Default
|
117
75
|
#
|
118
|
-
# The default mapper is Solrizer::FieldMapper
|
76
|
+
# The default mapper is Solrizer::FieldMapper. You can customize the default mapping by subclassing it.
|
119
77
|
# For example, to override the ID field name and the default suffix for sortable, and inherit everything else:
|
120
78
|
#
|
121
|
-
# class CustomMapperBasedOnDefault < Solrizer::FieldMapper
|
122
|
-
# id_field 'guid'
|
123
|
-
#
|
79
|
+
# class CustomMapperBasedOnDefault < Solrizer::FieldMapper
|
80
|
+
# self.id_field = 'guid'
|
81
|
+
#
|
82
|
+
# module MyCustomIndexDescriptors
|
83
|
+
# def self.my_converter
|
84
|
+
# @my_converter ||= Descriptor.new(:string, :stored, :indexed, :multivalued)
|
85
|
+
# end
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# self.descriptors = [MyCustomIndexDescriptors, DefaultDescriptors]
|
124
89
|
# end
|
125
90
|
|
126
91
|
class FieldMapper
|
127
92
|
|
128
93
|
include Loggable
|
129
94
|
|
130
|
-
# ------
|
95
|
+
# ------ Instance methods ------
|
131
96
|
|
132
|
-
|
97
|
+
attr_reader :id_field, :default_index_types
|
98
|
+
class_attribute :id_field
|
99
|
+
class_attribute :descriptors
|
100
|
+
# set defaults
|
101
|
+
self.descriptors = [DefaultDescriptors]
|
102
|
+
self.id_field = 'id'
|
103
|
+
|
133
104
|
|
134
|
-
def
|
135
|
-
|
136
|
-
@id_field = field_name
|
137
|
-
end
|
105
|
+
def initialize
|
106
|
+
self.id_field = self.class.id_field
|
138
107
|
end
|
108
|
+
|
109
|
+
# Given a specific field name, data type, and index type, returns the corresponding solr name.
|
139
110
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
111
|
+
# TODO field type is the input format, maybe we could just detect that?
|
112
|
+
# @param index_type is a FieldDescriptor
|
113
|
+
def solr_name(field_name, *opts)
|
114
|
+
index_type, args = if opts.first.kind_of? Hash
|
115
|
+
[:searchable, opts.first]
|
116
|
+
elsif opts.empty?
|
117
|
+
[:searchable, {type: :text}]
|
118
|
+
else
|
119
|
+
[opts[0], opts[1] || {}]
|
145
120
|
end
|
146
|
-
end
|
147
|
-
|
148
|
-
# Loads solr mappings from yml file.
|
149
|
-
# Assumes that string values are solr field name suffixes.
|
150
|
-
# This is meant as a simple entry point for working with solr mappings. For more powerful control over solr mappings, create your own subclasses of FieldMapper instead of using a yml file.
|
151
|
-
# @param [String] config_path This is the path to the directory where your mappings file is stored. Defaults to "Rails.root/config/solr_mappings.yml"
|
152
|
-
def self.load_mappings( config_path=nil )
|
153
121
|
|
154
|
-
|
155
|
-
|
156
|
-
config_path = File.join(Rails.root, "config", "solr_mappings.yml")
|
157
|
-
end
|
158
|
-
# Default to using the config file within the gem
|
159
|
-
if !File.exist?(config_path.to_s)
|
160
|
-
config_path = File.join(File.dirname(__FILE__), "..", "..", "config", "solr_mappings.yml")
|
161
|
-
end
|
162
|
-
end
|
122
|
+
indexer(index_type).name_and_converter(field_name, args).first
|
123
|
+
end
|
163
124
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
self.
|
168
|
-
|
169
|
-
|
170
|
-
id_field_from_file = mappings_from_file.delete("id")
|
171
|
-
if id_field_from_file.nil?
|
172
|
-
id_field "id"
|
125
|
+
# @param index_type [Symbol]
|
126
|
+
# search through the descriptors (class attribute) until a module is found that responds to index_type, then call it.
|
127
|
+
def index_type_macro(index_type)
|
128
|
+
klass = self.class.descriptors.find { |klass| klass.respond_to? index_type}
|
129
|
+
if klass
|
130
|
+
klass.send(index_type)
|
173
131
|
else
|
174
|
-
|
132
|
+
raise UnknownIndexMacro, "Unable to find `#{index_type}' in #{self.class.descriptors}"
|
175
133
|
end
|
176
|
-
|
177
|
-
default_index_type = mappings_from_file.delete("default")
|
178
|
-
mappings_from_file.each_pair do |index_type, type_settings|
|
179
|
-
if type_settings.kind_of?(Hash)
|
180
|
-
index_as index_type.to_sym, :default => index_type == default_index_type do |t|
|
181
|
-
type_settings.each_pair do |field_type, suffix|
|
182
|
-
eval("t.#{field_type} :suffix=>\"#{suffix}\"")
|
183
|
-
end
|
184
|
-
end
|
185
|
-
else
|
186
|
-
index_as index_type.to_sym, :default => index_type == default_index_type, :suffix=>type_settings
|
187
|
-
end
|
188
|
-
end
|
189
134
|
end
|
190
135
|
|
191
|
-
#
|
192
|
-
def
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
mapper.instance_eval &block
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
def self.apply_instance_init_actions(instance)
|
206
|
-
if self.superclass.respond_to? :apply_instance_init_actions
|
207
|
-
self.superclass.apply_instance_init_actions(instance)
|
208
|
-
end
|
209
|
-
@@instance_init_actions[self].each do |action|
|
210
|
-
action.call(instance)
|
136
|
+
# # @param index_type is a FieldDescriptor or a symbol that points to a method that returns a field descriptor
|
137
|
+
def indexer(index_type)
|
138
|
+
index_type = case index_type
|
139
|
+
when Symbol
|
140
|
+
index_type_macro(index_type)
|
141
|
+
when Array
|
142
|
+
raise "It's not yet supposed to be an array"
|
143
|
+
#IndexDescriptors::Descriptor.new(*index_type)
|
144
|
+
else
|
145
|
+
index_type
|
211
146
|
end
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
public
|
216
|
-
|
217
|
-
# ------ Instance methods ------
|
218
|
-
|
219
|
-
attr_reader :id_field, :default_index_types, :mappings
|
220
|
-
|
221
|
-
def initialize
|
222
|
-
@mappings = {}
|
223
|
-
self.class.apply_instance_init_actions(self)
|
224
|
-
@default_index_types = @mappings.select { |ix_type, mapping| mapping.opts[:default] }.map(&:first)
|
147
|
+
|
148
|
+
raise InvalidIndexDescriptor, "index type should be an IndexDescriptor, you passed: #{index_type}" unless index_type.kind_of? Descriptor
|
149
|
+
index_type
|
225
150
|
end
|
226
151
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
152
|
+
def extract_type(value)
|
153
|
+
case value
|
154
|
+
when NilClass
|
155
|
+
when Fixnum
|
156
|
+
:integer
|
157
|
+
else
|
158
|
+
value.class.to_s.underscore.to_sym
|
159
|
+
end
|
232
160
|
end
|
233
161
|
|
234
162
|
# Given a field name-value pair, a data type, and an array of index types, returns a hash of
|
235
163
|
# mapped names and values. The values in the hash are _arrays_, and may contain multiple values.
|
236
164
|
|
237
|
-
def solr_names_and_values(field_name, field_value,
|
238
|
-
|
165
|
+
def solr_names_and_values(field_name, field_value, index_types)
|
166
|
+
return {} unless field_value
|
239
167
|
|
168
|
+
# Determine the set of index types, adding defaults and removing not_xyz
|
240
169
|
index_types ||= []
|
241
|
-
index_types += default_index_types
|
242
170
|
index_types.uniq!
|
243
171
|
index_types.dup.each do |index_type|
|
244
172
|
if index_type.to_s =~ /^not_(.*)/
|
@@ -253,19 +181,21 @@ module Solrizer
|
|
253
181
|
|
254
182
|
index_types.each do |index_type|
|
255
183
|
# Get mapping for field
|
256
|
-
name,
|
184
|
+
name, converter = indexer(index_type).name_and_converter(field_name, type: extract_type(field_value))
|
185
|
+
#name, converter = solr_name_and_converter(field_name, index_type, field_type)
|
257
186
|
next unless name
|
258
187
|
|
259
188
|
# Is there a custom converter?
|
260
|
-
|
261
|
-
|
189
|
+
# TODO instead of a custom converter, look for input data type and output data type. Create a few methods that can do that cast.
|
190
|
+
|
191
|
+
value = if converter
|
262
192
|
if converter.arity == 1
|
263
193
|
converter.call(field_value)
|
264
194
|
else
|
265
195
|
converter.call(field_value, field_name)
|
266
196
|
end
|
267
197
|
else
|
268
|
-
field_value
|
198
|
+
field_value.to_s
|
269
199
|
end
|
270
200
|
|
271
201
|
# Add mapped name & value, unless it's a duplicate
|
@@ -275,116 +205,5 @@ module Solrizer
|
|
275
205
|
|
276
206
|
results
|
277
207
|
end
|
278
|
-
|
279
|
-
private
|
280
|
-
|
281
|
-
def solr_name_and_mappings(field_name, field_type, index_type)
|
282
|
-
field_name = field_name.to_s
|
283
|
-
mapping = @mappings[index_type]
|
284
|
-
unless mapping
|
285
|
-
logger.debug "Unknown index type '#{index_type}' for field #{field_name}"
|
286
|
-
return nil
|
287
|
-
end
|
288
|
-
|
289
|
-
data_type_mapping = mapping.data_types[field_type] || mapping.data_types[:default]
|
290
|
-
|
291
|
-
suffix = data_type_mapping.opts[:suffix] if data_type_mapping
|
292
|
-
suffix ||= mapping.opts[:suffix]
|
293
|
-
name = field_name + suffix
|
294
|
-
|
295
|
-
[name, mapping, data_type_mapping]
|
296
|
-
end
|
297
|
-
|
298
|
-
class IndexTypeMapping
|
299
|
-
attr_accessor :opts, :data_types
|
300
|
-
|
301
|
-
def initialize
|
302
|
-
@opts = {}
|
303
|
-
@data_types = {}
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
class DataTypeMapping
|
308
|
-
attr_accessor :opts, :converter
|
309
|
-
|
310
|
-
def initialize
|
311
|
-
@opts = {}
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
class DataTypeMappingBuilder
|
316
|
-
def initialize(index_type_mapping)
|
317
|
-
@index_type_mapping = index_type_mapping
|
318
|
-
end
|
319
|
-
|
320
|
-
def method_missing(method, *args, &block)
|
321
|
-
data_type_mapping = (@index_type_mapping.data_types[method] ||= DataTypeMapping.new)
|
322
|
-
data_type_mapping.opts.merge! args[0] if args.length > 0
|
323
|
-
data_type_mapping.converter = block if block_given?
|
324
|
-
end
|
325
|
-
end
|
326
|
-
|
327
|
-
# ------ Default mapper ------
|
328
|
-
|
329
|
-
public
|
330
|
-
|
331
|
-
module Defaults
|
332
|
-
extend ActiveSupport::Concern
|
333
|
-
included do
|
334
|
-
id_field 'id'
|
335
|
-
index_as :searchable do |t|
|
336
|
-
t.default :suffix => '_t'
|
337
|
-
t.date :suffix => '_dt' do |value|
|
338
|
-
iso8601_date(value)
|
339
|
-
end
|
340
|
-
t.string :suffix => '_t'
|
341
|
-
t.text :suffix => '_t'
|
342
|
-
t.symbol :suffix => '_s'
|
343
|
-
t.integer :suffix => '_i'
|
344
|
-
t.long :suffix => '_l'
|
345
|
-
t.boolean :suffix => '_b'
|
346
|
-
t.float :suffix => '_f'
|
347
|
-
t.double :suffix => '_d'
|
348
|
-
end
|
349
|
-
index_as :displayable, :suffix => '_display' do |t|
|
350
|
-
t.date do |value|
|
351
|
-
value.to_s
|
352
|
-
end
|
353
|
-
end
|
354
|
-
index_as :facetable, :suffix => '_facet' do |t|
|
355
|
-
t.date do |value|
|
356
|
-
value.to_s
|
357
|
-
end
|
358
|
-
end
|
359
|
-
|
360
|
-
index_as :sortable, :suffix => '_sort' do |t|
|
361
|
-
t.date do |value|
|
362
|
-
value.to_s
|
363
|
-
end
|
364
|
-
end
|
365
|
-
|
366
|
-
index_as :unstemmed_searchable, :suffix => '_unstem_search'
|
367
|
-
end
|
368
|
-
end
|
369
|
-
|
370
|
-
class Default < FieldMapper
|
371
|
-
include Defaults
|
372
|
-
end
|
373
|
-
|
374
|
-
protected
|
375
|
-
|
376
|
-
def self.iso8601_date(value)
|
377
|
-
begin
|
378
|
-
if value.is_a?(Date)
|
379
|
-
DateTime.parse(value.to_s).to_time.utc.iso8601
|
380
|
-
elsif !value.empty?
|
381
|
-
DateTime.parse(value).to_time.utc.iso8601
|
382
|
-
end
|
383
|
-
rescue ArgumentError => e
|
384
|
-
raise ArgumentError, "Unable to parse `#{value}' as a date-time object"
|
385
|
-
end
|
386
|
-
end
|
387
|
-
|
388
208
|
end
|
389
|
-
|
390
209
|
end
|
data/lib/solrizer/version.rb
CHANGED
@@ -8,21 +8,21 @@ module Solrizer::XML::Extractor
|
|
8
8
|
#
|
9
9
|
# @param [xml] text xml content to index
|
10
10
|
# @param [Hash] solr_doc
|
11
|
-
def xml_to_solr( text, solr_doc=Hash.new )
|
11
|
+
def xml_to_solr( text, solr_doc=Hash.new, mapper = Solrizer.default_field_mapper )
|
12
12
|
doc = XmlSimple.xml_in( text )
|
13
13
|
|
14
14
|
doc.each_pair do |name, value|
|
15
15
|
if value.kind_of?(Array)
|
16
16
|
if value.first.kind_of?(Hash)
|
17
17
|
# This deals with the way xml-simple handles nodes with attributes
|
18
|
-
solr_doc.merge!({
|
18
|
+
solr_doc.merge!({mapper.solr_name(name, :searchable, :type=>:text).to_sym => "#{value.first["content"]}"})
|
19
19
|
elsif value.length > 1
|
20
|
-
solr_doc.merge!({
|
20
|
+
solr_doc.merge!({mapper.solr_name(name, :searchable, :type=>:text).to_sym => value})
|
21
21
|
else
|
22
|
-
solr_doc.merge!({
|
22
|
+
solr_doc.merge!({mapper.solr_name(name, :searchable, :type=>:text).to_sym => "#{value.first}"})
|
23
23
|
end
|
24
24
|
else
|
25
|
-
solr_doc.merge!({
|
25
|
+
solr_doc.merge!({mapper.solr_name(name, :searchable, :type=>:text).to_sym => "#{value}"})
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -35,17 +35,10 @@ module Solrizer::XML::TerminologyBasedSolrizer
|
|
35
35
|
nodeset = doc.term_values(*term_pointer)
|
36
36
|
|
37
37
|
nodeset.each do |n|
|
38
|
-
|
39
|
-
# TODO: Solrizer::FieldMapper::Default is supposed to translate dates into full ISO 8601 formatted strings.
|
40
|
-
# However, there an integration issue with ActiveFedora using OM: it ignores the default field mapper given
|
41
|
-
# in this gem that does this. So, the following is a workaround until it is fixed.
|
42
|
-
node = n.is_a?(Date) ? DateTime.parse(n.to_s).to_time.utc.iso8601 : n.to_s
|
43
|
-
|
44
|
-
doc.solrize_node(node.to_s, term_pointer, term, solr_doc, field_mapper)
|
38
|
+
doc.solrize_node(n, term_pointer, term, solr_doc, field_mapper)
|
45
39
|
unless term.kind_of? OM::XML::NamedTermProxy
|
46
40
|
term.children.each_pair do |child_term_name, child_term|
|
47
|
-
|
48
|
-
doc.solrize_term(child_term, solr_doc, field_mapper, opts={:parents=>parents+[{term.name=>nodeset.index(node.to_s)}]})
|
41
|
+
doc.solrize_term(child_term, solr_doc, field_mapper, opts={:parents=>parents+[{term.name=>nodeset.index(n)}]})
|
49
42
|
end
|
50
43
|
end
|
51
44
|
end
|
@@ -63,26 +56,17 @@ module Solrizer::XML::TerminologyBasedSolrizer
|
|
63
56
|
# @return [Hash] the solr doc
|
64
57
|
def solrize_node(node_value, doc, term_pointer, term, solr_doc = Hash.new, field_mapper = nil, opts = {})
|
65
58
|
return solr_doc unless term.index_as && !term.index_as.empty?
|
66
|
-
|
67
|
-
directive = term_to_solrizer_directive(term)
|
68
59
|
|
69
60
|
generic_field_name_base = OM::XML::Terminology.term_generic_name(*term_pointer)
|
70
|
-
create_and_insert_terms(generic_field_name_base, node_value,
|
71
|
-
|
61
|
+
create_and_insert_terms(generic_field_name_base, node_value, term.index_as, solr_doc)
|
72
62
|
|
73
63
|
if term_pointer.length > 1
|
74
64
|
hierarchical_field_name_base = OM::XML::Terminology.term_hierarchical_name(*term_pointer)
|
75
|
-
create_and_insert_terms(hierarchical_field_name_base, node_value,
|
65
|
+
create_and_insert_terms(hierarchical_field_name_base, node_value, term.index_as, solr_doc)
|
76
66
|
end
|
77
67
|
solr_doc
|
78
68
|
end
|
79
69
|
|
80
|
-
private
|
81
|
-
|
82
|
-
def term_to_solrizer_directive(term)
|
83
|
-
Solrizer::Directive.new(term.type, term.index_as)
|
84
|
-
end
|
85
|
-
|
86
70
|
end
|
87
71
|
|
88
72
|
|
data/lib/solrizer.rb
CHANGED
data/solrizer.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.add_dependency "stomp"
|
20
20
|
s.add_dependency "daemons"
|
21
21
|
s.add_dependency "activesupport"
|
22
|
-
s.add_development_dependency 'rspec'
|
22
|
+
s.add_development_dependency 'rspec'
|
23
23
|
s.add_development_dependency 'rake'
|
24
24
|
s.add_development_dependency 'yard'
|
25
25
|
s.add_development_dependency 'RedCloth' # yard depends on redcloth
|
@@ -76,7 +76,6 @@ module Samples
|
|
76
76
|
t.url(:path=>"url")
|
77
77
|
}
|
78
78
|
t.publication_url(:proxy=>[:location,:url])
|
79
|
-
t.root_title(:proxy => [:mods, :title_info, :main_title], :index_as => [:searchable])
|
80
79
|
t.title(:proxy=>[:title_info, :main_title])
|
81
80
|
t.journal_title(:proxy=>[:journal, :title_info, :main_title])
|
82
81
|
t.pub_date(:proxy=>[:journal, :issue, :publication_date])
|
data/spec/spec_helper.rb
CHANGED
data/spec/units/common_spec.rb
CHANGED
@@ -12,28 +12,24 @@ describe Solrizer::Common do
|
|
12
12
|
|
13
13
|
it "should handle many field types" do
|
14
14
|
solr_doc = {}
|
15
|
-
|
16
|
-
|
17
|
-
solr_doc.should == {'my_name_t' => ['value'], 'my_name_sort' => ['value'], 'my_name_display' => ['value']}
|
15
|
+
Foo.create_and_insert_terms('my_name', 'value', [:displayable, :searchable, :sortable], solr_doc)
|
16
|
+
solr_doc.should == {'my_name_ssm' => ['value'], 'my_name_ssi' => ['value'], 'my_name_tesim' => ['value']}
|
18
17
|
end
|
19
18
|
it "should handle dates that are searchable" do
|
20
19
|
solr_doc = {}
|
21
|
-
|
22
|
-
|
23
|
-
solr_doc.should == {'my_name_dt' => ['2013-01-10T00:00:00Z']}
|
20
|
+
Foo.create_and_insert_terms('my_name', Date.parse('2013-01-10'), [:searchable], solr_doc)
|
21
|
+
solr_doc.should == {'my_name_dtsi' => ['2013-01-10T00:00:00Z']}
|
24
22
|
end
|
25
23
|
|
26
24
|
it "should handle dates that are displayable" do
|
27
25
|
solr_doc = {}
|
28
|
-
|
29
|
-
|
30
|
-
solr_doc.should == {'my_name_display' => ['2013-01-10']}
|
26
|
+
Foo.create_and_insert_terms('my_name', Date.parse('2013-01-10'), [:displayable], solr_doc)
|
27
|
+
solr_doc.should == {'my_name_ssm' => ['2013-01-10']}
|
31
28
|
end
|
32
29
|
|
33
30
|
it "should handle dates that are sortable" do
|
34
31
|
solr_doc = {}
|
35
|
-
|
36
|
-
|
37
|
-
solr_doc.should == {'my_name_sort' => ['2013-01-10']}
|
32
|
+
Foo.create_and_insert_terms('my_name', Date.parse('2013-01-10'), [:sortable], solr_doc)
|
33
|
+
solr_doc.should == {'my_name_ssi' => ['2013-01-10']}
|
38
34
|
end
|
39
35
|
end
|
@@ -22,8 +22,9 @@ describe Solrizer::Extractor do
|
|
22
22
|
|
23
23
|
describe "#insert_solr_field_value" do
|
24
24
|
it "should initialize a solr doc list if it is nil" do
|
25
|
-
solr_doc = {'
|
26
|
-
Solrizer::Extractor.insert_solr_field_value(solr_doc, '
|
25
|
+
solr_doc = {'title_tesim' => nil }
|
26
|
+
Solrizer::Extractor.insert_solr_field_value(solr_doc, 'title_tesim', 'Frank')
|
27
|
+
solr_doc.should == {"title_tesim"=>["Frank"]}
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|