Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Inserting single value fields (e.g. :sortable) should not cause a solr

error. Fixes #16
  • Loading branch information...
commit d876a4366afbe79a694bc190e062a098b0381d89 1 parent b1b7030
@jcoyne jcoyne authored
View
3  History.txt
@@ -1,3 +1,6 @@
+h2. 3.0.1
+ #16 Inserting non-multivalued fields should not create a solr error
+
h2. 3.0.0 (2013-03-28)
suffix changes:
_s -> _sim
View
7 lib/solrizer.rb
@@ -7,6 +7,7 @@ module Solrizer
autoload :Descriptor
autoload :FieldMapper
autoload :DefaultDescriptors
+ autoload :Suffix
autoload :HTML, 'solrizer/html'
autoload :VERSION, 'solrizer/version'
autoload :XML, 'solrizer/xml'
@@ -38,7 +39,11 @@ def self.insert_field(doc, name, value, *indexer_args)
indexer_args = [:stored_searchable] if indexer_args.empty?
default_field_mapper.solr_names_and_values(name, value, indexer_args).each do |k, v|
doc[k] ||= []
- doc[k] += v
+ if v.is_a? Array
+ doc[k] += v
+ else
+ doc[k] = v
+ end
end
doc
end
View
6 lib/solrizer/common.rb
@@ -12,10 +12,8 @@ module ClassMethods
# @param [Array] index_as list of indexers to use (e.g. [:searchable, :facetable])
# @param [Hash] solr_doc the solr_doc to insert into.
def create_and_insert_terms(field_name_base, value, index_as, solr_doc)
- Solrizer.default_field_mapper.solr_names_and_values(field_name_base, value, index_as).each do |field_name, field_value|
- unless field_value.join("").strip.empty?
- ::Solrizer::Extractor.insert_solr_field_value(solr_doc, field_name, field_value)
- end
+ index_as.each do |indexer|
+ Solrizer.insert_field(solr_doc, field_name_base, value, indexer)
end
end
end
View
43 lib/solrizer/descriptor.rb
@@ -15,7 +15,7 @@ def name_and_converter(field_name, args=nil)
args ||= {}
field_type = args[:type]
if type_required?
- raise "Must provide a :type argument when index_type is `#{self}' for #{field_name}" unless field_type
+ raise ArgumentError, "Must provide a :type argument when index_type is `#{self}' for #{field_name}" unless field_type
end
[field_name.to_s + suffix(field_type), converter(field_type)]
end
@@ -24,45 +24,20 @@ def type_required?
@type_required
end
+ def evaluate_suffix(field_type)
+ Suffix.new(index_type.first.kind_of?(Proc) ? index_type.first.call(field_type) : index_type.dup)
+ end
+
protected
- def suffix(field_type)
- evaluated_type = index_type.first.kind_of?(Proc) ? index_type.first.call(field_type) : index_type.dup
- stored_suffix = config[:stored_suffix] if evaluated_type.delete(:stored)
- index_suffix = config[:index_suffix] if evaluated_type.delete(:indexed)
- multivalued_suffix = config[:multivalued_suffix] if evaluated_type.delete(:multivalued)
- index_datatype = evaluated_type.first
- raise Solrizer::InvalidIndexDescriptor, "Missing datatype for #{evaluated_type}" unless index_datatype
- type_suffix = config[:type_suffix].call(index_datatype)
- raise Solrizer::InvalidIndexDescriptor, "Invalid datatype `#{index_datatype.inspect}'. Must be one of: :date, :time, :text, :text_en, :string, :integer" unless type_suffix
- suffix = [config[:suffix_delimiter], type_suffix, stored_suffix, index_suffix, multivalued_suffix].join
+
+ # Suffix can be overridden if you want a different method of grabbing the suffix
+ def suffix(field_type)
+ evaluate_suffix(field_type).to_s
end
def converter(field_type)
@converter.call(field_type) if @converter
end
-
- private
- def config
- @config ||=
- {suffix_delimiter: '_',
- type_suffix: lambda do |type|
- case type
- when :string, :symbol # TODO `:symbol' usage ought to be deprecated
- 's'
- when :text
- 't'
- when :text_en
- 'te'
- when :date, :time
- 'dt'
- when :integer
- 'i'
- end
- end,
- stored_suffix: 's',
- index_suffix: 'i',
- multivalued_suffix: 'm'}
- end
end
end
View
7 lib/solrizer/extractor.rb
@@ -18,8 +18,11 @@ class Extractor
# @param [String] field_value
def self.insert_solr_field_value(solr_doc, field_name, field_value)
formatted_value = self.format_node_value(field_value)
- solr_doc[field_name] ||= []
- solr_doc[field_name] << formatted_value
+ if solr_doc[field_name]
+ solr_doc[field_name] = Array(solr_doc[field_name]) << formatted_value
+ else
+ solr_doc[field_name] = formatted_value
+ end
return solr_doc
end
View
14 lib/solrizer/field_mapper.rb
@@ -201,8 +201,9 @@ def solr_names_and_values(field_name, field_value, index_types)
index_types.each do |index_type|
Array(field_value).each do |single_value|
# Get mapping for field
- name, converter = indexer(index_type).name_and_converter(field_name, type: extract_type(single_value))
- #name, converter = solr_name_and_converter(field_name, index_type, field_type)
+ descriptor = indexer(index_type)
+ data_type = extract_type(single_value)
+ name, converter = descriptor.name_and_converter(field_name, type: data_type)
next unless name
# Is there a custom converter?
@@ -219,8 +220,13 @@ def solr_names_and_values(field_name, field_value, index_types)
end
# Add mapped name & value, unless it's a duplicate
- values = (results[name] ||= [])
- values << value unless value.nil? || values.include?(value)
+ if descriptor.evaluate_suffix(data_type).multivalued?
+ values = (results[name] ||= [])
+ values << value unless value.nil? || values.include?(value)
+ else
+ logger.warn "Setting #{name} to `#{value}', but it already had `#{results[name]}'" if results[name]
+ results[name] = value
+ end
end
end
View
59 lib/solrizer/suffix.rb
@@ -0,0 +1,59 @@
+module Solrizer
+ class Suffix
+
+ def initialize(fields)
+ @fields = fields
+ end
+
+ def multivalued?
+ @fields.include? :multivalued
+ end
+
+ def stored?
+ @fields.include? :stored
+ end
+
+ def indexed?
+ @fields.include? :indexed
+ end
+
+ def data_type
+ @fields.first
+ end
+
+ def to_s
+ stored_suffix = config[:stored_suffix] if stored?
+ index_suffix = config[:index_suffix] if indexed?
+ multivalued_suffix = config[:multivalued_suffix] if multivalued?
+ raise Solrizer::InvalidIndexDescriptor, "Missing datatype for #{@fields}" unless data_type
+ type_suffix = config[:type_suffix].call(data_type)
+ raise Solrizer::InvalidIndexDescriptor, "Invalid datatype `#{data_type.inspect}'. Must be one of: :date, :time, :text, :text_en, :string, :integer" unless type_suffix
+
+ [config[:suffix_delimiter], type_suffix, stored_suffix, index_suffix, multivalued_suffix].join
+ end
+
+
+ private
+ def config
+ @config ||=
+ {suffix_delimiter: '_',
+ type_suffix: lambda do |type|
+ case type
+ when :string, :symbol # TODO `:symbol' usage ought to be deprecated
+ 's'
+ when :text
+ 't'
+ when :text_en
+ 'te'
+ when :date, :time
+ 'dt'
+ when :integer
+ 'i'
+ end
+ end,
+ stored_suffix: 's',
+ index_suffix: 'i',
+ multivalued_suffix: 'm'}
+ end
+ end
+end
View
6 spec/units/common_spec.rb
@@ -13,7 +13,7 @@ class Foo
it "should handle many field types" do
solr_doc = {}
Foo.create_and_insert_terms('my_name', 'value', [:displayable, :searchable, :sortable], solr_doc)
- solr_doc.should == {'my_name_ssm' => ['value'], 'my_name_si' => ['value'], 'my_name_teim' => ['value']}
+ solr_doc.should == {'my_name_ssm' => ['value'], 'my_name_si' => 'value', 'my_name_teim' => ['value']}
end
it "should handle dates that are searchable" do
@@ -25,7 +25,7 @@ class Foo
it "should handle dates that are stored_sortable" do
solr_doc = {}
Foo.create_and_insert_terms('my_name', Date.parse('2013-01-10'), [:stored_sortable], solr_doc)
- solr_doc.should == {'my_name_dtsi' => ['2013-01-10T00:00:00Z']}
+ solr_doc.should == {'my_name_dtsi' => '2013-01-10T00:00:00Z'}
end
it "should handle dates that are displayable" do
@@ -37,6 +37,6 @@ class Foo
it "should handle dates that are sortable" do
solr_doc = {}
Foo.create_and_insert_terms('my_name', Date.parse('2013-01-10'), [:sortable], solr_doc)
- solr_doc.should == {'my_name_dti' => ['2013-01-10T00:00:00Z']}
+ solr_doc.should == {'my_name_dti' => '2013-01-10T00:00:00Z'}
end
end
View
15 spec/units/extractor_spec.rb
@@ -24,8 +24,21 @@
it "should initialize a solr doc list if it is nil" do
solr_doc = {'title_tesim' => nil }
Solrizer::Extractor.insert_solr_field_value(solr_doc, 'title_tesim', 'Frank')
- solr_doc.should == {"title_tesim"=>["Frank"]}
+ solr_doc.should == {"title_tesim"=>"Frank"}
end
+ it "should insert multiple" do
+ solr_doc = {'title_tesim' => nil }
+ Solrizer::Extractor.insert_solr_field_value(solr_doc, 'title_tesim', 'Frank')
+ Solrizer::Extractor.insert_solr_field_value(solr_doc, 'title_tesim', 'Margret')
+ Solrizer::Extractor.insert_solr_field_value(solr_doc, 'title_tesim', 'Joyce')
+ solr_doc.should == {"title_tesim"=>["Frank", 'Margret', 'Joyce']}
+ end
+ it "should not make a list if a single valued field is passed in" do
+ solr_doc = {}
+ Solrizer::Extractor.insert_solr_field_value(solr_doc, 'title_dtsi', '2013-03-22T12:33:00Z')
+ solr_doc.should == {"title_dtsi"=>"2013-03-22T12:33:00Z"}
+ end
+
end
end
View
20 spec/units/field_mapper_spec.rb
@@ -37,18 +37,27 @@ class UnstemmedDescriptor < Solrizer::Descriptor
def name_and_converter(field_name, args)
[field_name + '_s', lambda { |value| "#{value} o'clock" }]
end
+ def index_type
+ [:multivalued]
+ end
end
class StoredSearchableDescriptor < Solrizer::Descriptor
def name_and_converter(field_name, args)
[field_name.to_s + '_s']
end
+ def index_type
+ [:multivalued]
+ end
end
class EdibleDescriptor < Solrizer::Descriptor
def name_and_converter(field_name, args)
[field_name + '_food']
end
+ def index_type
+ [:multivalued]
+ end
end
class FungibleDescriptor < Solrizer::Descriptor
@@ -94,6 +103,9 @@ def laughable_converter(type)
end
end
end
+ def index_type
+ [:multivalued]
+ end
end
end
@@ -270,16 +282,16 @@ def fungible_type(type)
"foo_tesim" => ["bar"], #stored_searchable
"foo_ssm" => ["bar"], #displayable
"foo_sim" => ["bar"], #facetable
- "foo_si" => ["bar"], #sortable
- "foo_ssi" => ["bar"], #stored_sortable
+ "foo_si" => "bar", #sortable
+ "foo_ssi" => "bar", #stored_sortable
"foo_tim" => ["bar"] #unstemmed_searchable
}
end
it "should support stored_sortable" do
time = Time.iso8601("2012-11-06T15:16:17Z")
- @mapper.solr_names_and_values('foo', time, :stored_sortable).should == {"foo_dtsi" => ["2012-11-06T15:16:17Z"]}
- @mapper.solr_names_and_values('foo', 'bar', :stored_sortable).should == {"foo_ssi" => ["bar"]}
+ @mapper.solr_names_and_values('foo', time, :stored_sortable).should == {"foo_dtsi" => "2012-11-06T15:16:17Z"}
+ @mapper.solr_names_and_values('foo', 'bar', :stored_sortable).should == {"foo_ssi" => "bar"}
end
end
end
View
17 spec/units/solrizer_spec.rb
@@ -9,9 +9,13 @@
Solrizer.insert_field(doc, 'foo', 'A name')
doc.should == {'foo_tesim' => ['A name']}
end
+ it "should not create an array of fields that are not multivalued" do
+ Solrizer.insert_field(doc, 'foo', 'A name', :sortable)
+ doc.should == {'foo_si' => 'A name'}
+ end
it "should insert a field with multiple indexers" do
Solrizer.insert_field(doc, 'foo', 'A name', :sortable, :facetable)
- doc.should == {'foo_si' => ['A name'], 'foo_sim' => ['A name']}
+ doc.should == {'foo_si' => 'A name', 'foo_sim' => ['A name']}
end
it "should insert Dates" do
Solrizer.insert_field(doc, 'foo', Date.parse('2013-01-13'))
@@ -24,17 +28,16 @@
it "should insert multiple values" do
Solrizer.insert_field(doc, 'foo', ['A name', 'B name'], :sortable, :facetable)
- # NOTE: is this desired behavior for non-multivalued fields, like :sortable ?
- doc.should == {'foo_si' => ['A name', 'B name'], 'foo_sim' => ['A name', 'B name']}
+ doc.should == {'foo_si' => 'B name', 'foo_sim' => ['A name', 'B name']}
end
end
describe "on a document with values" do
- before{ @doc = {'foo_si' => ['A name'], 'foo_sim' => ['A name']}}
+ before{ @doc = {'foo_si' => 'A name', 'foo_sim' => ['A name']}}
- it "should not overwrite values that exist before" do
+ it "should not overwrite muli-values that exist before" do
Solrizer.insert_field(@doc, 'foo', 'B name', :sortable, :facetable)
- @doc.should == {'foo_si' => ['A name', 'B name'], 'foo_sim' => ['A name', 'B name']}
+ @doc.should == {'foo_si' => 'B name', 'foo_sim' => ['A name', 'B name']}
end
end
end
@@ -44,7 +47,7 @@
it "should overwrite values that exist before" do
Solrizer.set_field(@doc, 'foo', 'B name', :sortable, :facetable)
- @doc.should == {'foo_si' => ['B name'], 'foo_sim' => ['B name']}
+ @doc.should == {'foo_si' => 'B name', 'foo_sim' => ['B name']}
end
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.