lib/supernova/solr_indexer.rb in supernova-0.2.2 vs lib/supernova/solr_indexer.rb in supernova-0.3.0

- old
+ new

@@ -1,27 +1,146 @@ require "json" class Supernova::SolrIndexer - attr_accessor :options, :db + attr_accessor :options, :db, :ids attr_writer :index_file_path + class << self + def field_definitions + @field_definitions ||= {} + end + + def has(key, attributes) + field_definitions[key] = attributes + end + + def clazz(class_name =:only_return) + @clazz = class_name if class_name != :only_return + @clazz + end + + def table_name(name = :only_return) + @table_name = name if name != :only_return + @table_name + end + + def method_missing(*args) + criteria = Supernova::SolrCriteria.new(self.clazz).attribute_mapping(self.field_definitions) + if criteria.respond_to?(args.first) + criteria.send(*args) + else + super + end + end + end + + FIELD_SUFFIX_MAPPING = { + :raw => nil, + :string => :s, + :text => :t, + :int => :i, + :integer => :i, + :sint => :si, + :float => :f, + :date => :dt, + :boolean => :b, + :location => :p + } + def initialize(options = {}) options.each do |key, value| self.send(:"#{key}=", value) if self.respond_to?(:"#{key}=") end self.options = options + self.ids ||= :all end + def index! + index_query(query_to_index) do |row| + row_to_solr(row) + end + end + + def row_to_solr(row) + row + end + + def table_name + self.class.table_name || (self.class.clazz && self.class.clazz.respond_to?(:table_name) ? self.class.clazz.table_name : nil) + end + + def query_to_index + raise "no table_name defined" if self.table_name.nil? + query = "SELECT #{select_fields.join(", ")} FROM #{self.table_name}" + query << " WHERE id IN (#{ids.join(", ")})" if ids_given? + query + end + + def default_fields + fields = ["id"] + fields << %("#{self.class.clazz}" AS type_s) if self.class.clazz + fields + end + + def defined_fields + self.class.field_definitions.map do |field, options| + sql_column_from_field_and_type(field, options[:type]) if options[:virtual] != true + end.compact + end + + def select_fields + default_fields + defined_fields + end + + def validate_lat(lat) + float_or_nil_when_abs_bigger_than(lat, 90) + end + + def validate_lng(lng) + float_or_nil_when_abs_bigger_than(lng, 180) + end + + def float_or_nil_when_abs_bigger_than(value, border) + return nil if value.to_s.strip.length == 0 + value_f = value.to_f + value_f.abs > border ? nil : value_f + end + + def sql_column_from_field_and_type(field, type) + return sql_date_column_from_field(field) if type == :date + if suffix = self.class.suffix_from_type(type) + "#{field} AS #{field}_#{suffix}" + else + raise "no suffix for #{type} defined" + end + end + + def self.suffix_from_type(type) + FIELD_SUFFIX_MAPPING[type.to_sym] + end + + def self.solr_field_for_field_name_and_mapping(field, mapping) + [field, mapping && mapping[field.to_sym] ? suffix_from_type(mapping[field.to_sym][:type]) : nil].compact.join("_") + end + + def sql_date_column_from_field(field) + %(IF(#{field} IS NULL, NULL, CONCAT(REPLACE(#{field}, " ", "T"), "Z")) AS #{field}_dt) + end + def query_db(query) db.send(db.respond_to?(:query) ? :query : :select_all, query) end def index_query(query) query_db(query).each do |row| yield(row) if block_given? write_to_file(row) end finish + end + + def ids_given? + self.ids.is_a?(Array) end def index_file_path @index_file_path ||= File.expand_path("/tmp/index_file_#{Time.now.to_i}.json") end \ No newline at end of file