Yoji Shidara
null+****@clear*****
Thu Dec 19 13:06:37 JST 2013
Yoji Shidara 2013-12-19 13:06:37 +0900 (Thu, 19 Dec 2013) New Revision: 896877990dbcc08851910db4d72b10ba0c5d5e73 https://github.com/droonga/fluent-plugin-droonga/commit/896877990dbcc08851910db4d72b10ba0c5d5e73 Merged ce62e72: Merge branch 'refactor-searcher' Message: Extract ResultFormatter from QuerySearcher Modified files: lib/droonga/searcher.rb Modified: lib/droonga/searcher.rb (+169 -151) =================================================================== --- lib/droonga/searcher.rb 2013-12-19 12:41:09 +0900 (382cf28) +++ lib/droonga/searcher.rb 2013-12-19 13:06:37 +0900 (b483b60) @@ -112,6 +112,172 @@ module Droonga end end + class ResultFormatter + def initialize(context, query, result, condition, count, start_time) + @context = context + @query = query + @result = result + @start_time = start_time + @count = count + @condition = condition + end + + def format + formatted_result = {} + format_count(formatted_result) + format_attributes(formatted_result) + format_records(formatted_result) + if need_element_output?("startTime") + formatted_result["startTime"] = @start_time.iso8601 + end + if need_element_output?("elapsedTime") + formatted_result["elapsedTime"] = Time.now.to_f - @start_time.to_f + end + formatted_result + end + + private + def need_element_output?(element) + params = @query["output"] + + elements = params["elements"] + return false if elements.nil? + + elements.include?(element) + end + + def format_count(formatted_result) + return unless need_element_output?("count") + formatted_result["count"] = @count + end + + def format_attributes(formatted_result) + return unless need_element_output?("attributes") + + # XXX IMPLEMENT ME!!! + attributes = nil + if @query["output"]["format"] == "complex" + # should convert columns to an object like: + # {"_id" => {"type" => "UInt32", "vector" => false}} + attributes = {} + else + # should convert columns to an object like: + # [{"name" => "_id", "type" => "UInt32", "vector" => false}] + attributes = [] + end + + formatted_result["attributes"] = attributes + end + + def format_records(formatted_result) + return unless need_element_output?("records") + + params = @query["output"] + + attributes = params["attributes"] + target_attributes = normalize_target_attributes(attributes) + offset = params["offset"] || 0 + limit = params["limit"] || 10 + @result.open_cursor(:offset => offset, :limit => limit) do |cursor| + if params["format"] == "complex" + formatted_result["records"] = cursor.collect do |record| + complex_record(target_attributes, record) + end + else + formatted_result["records"] = cursor.collect do |record| + simple_record(target_attributes, record) + end + end + end + end + + def complex_record(attributes, record) + values = {} + attributes.collect do |attribute| + values[attribute[:label]] = record_value(record, attribute) + end + values + end + + def simple_record(attributes, record) + attributes.collect do |attribute| + record_value(record, attribute) + end + end + + def record_value(record, attribute) + if attribute[:source] == "_subrecs" + if @query["output"]["format"] == "complex" + record.sub_records.collect do |sub_record| + target_attributes = resolve_attributes(attribute, sub_record) + complex_record(target_attributes, sub_record) + end + else + record.sub_records.collect do |sub_record| + target_attributes = resolve_attributes(attribute, sub_record) + simple_record(target_attributes, sub_record) + end + end + else + expression = attribute[:expression] + if expression + variable = attribute[:variable] + variable.value = record + expression.execute + else + value = record[attribute[:source]] + if value.is_a?(Groonga::Record) + value.record_id + else + value + end + end + end + end + + def resolve_attributes(attribute, record) + unless attribute[:target_attributes] + attribute[:target_attributes] = + normalize_target_attributes(attribute[:attributes], record.table) + end + return attribute[:target_attributes] + end + + def normalize_target_attributes(attributes, domain = @result) + attributes.collect do |attribute| + if attribute.is_a?(String) + attribute = { + "source" => attribute, + } + end + source = attribute["source"] + if accessor_name?(source) + expression = nil + variable = nil + else + expression = Groonga::Expression.new(context: @context) + variable = expression.define_variable(domain: domain) + expression.parse(source, syntax: :script) + condition = expression.define_variable(name: "$condition", + reference: true) + condition.value = @condition + source = nil + end + { + label: attribute["label"] || attribute["source"], + source: source, + expression: expression, + variable: variable, + attributes: attribute["attributes"] + } + end + end + + def accessor_name?(source) + /\A[a-zA-Z\#@$_][a-zA-Z\d\#@$_\-.]*\z/ === source + end + end + class QuerySearcher def initialize(context, query) @context = context @@ -130,17 +296,9 @@ module Droonga end def format - formatted_result = {} - format_count(formatted_result) - format_attributes(formatted_result) - format_records(formatted_result) - if need_element_output?("startTime") - formatted_result["startTime"] = @start_time.iso8601 - end - if need_element_output?("elapsedTime") - formatted_result["elapsedTime"] = Time.now.to_f - @start_time.to_f - end - formatted_result + # XXX too many arguments are passed to ResultFormatter + formatter = ResultFormatter.new(@context, @query, @result, @condition, @count, @start_time) + formatter.format end private @@ -290,146 +448,6 @@ module Droonga :by => sort_by) end - def need_element_output?(element) - params = @query["output"] - - elements = params["elements"] - return false if elements.nil? - - elements.include?(element) - end - - def format_count(formatted_result) - return unless need_element_output?("count") - formatted_result["count"] = @count - end - - def format_attributes(formatted_result) - return unless need_element_output?("attributes") - - # XXX IMPLEMENT ME!!! - attributes = nil - if @query["output"]["format"] == "complex" - # should convert columns to an object like: - # {"_id" => {"type" => "UInt32", "vector" => false}} - attributes = {} - else - # should convert columns to an object like: - # [{"name" => "_id", "type" => "UInt32", "vector" => false}] - attributes = [] - end - - formatted_result["attributes"] = attributes - end - - def format_records(formatted_result) - return unless need_element_output?("records") - - params = @query["output"] - - attributes = params["attributes"] - target_attributes = normalize_target_attributes(attributes) - offset = params["offset"] || 0 - limit = params["limit"] || 10 - @result.open_cursor(:offset => offset, :limit => limit) do |cursor| - if params["format"] == "complex" - formatted_result["records"] = cursor.collect do |record| - complex_record(target_attributes, record) - end - else - formatted_result["records"] = cursor.collect do |record| - simple_record(target_attributes, record) - end - end - end - end - - def complex_record(attributes, record) - values = {} - attributes.collect do |attribute| - values[attribute[:label]] = record_value(record, attribute) - end - values - end - - def simple_record(attributes, record) - attributes.collect do |attribute| - record_value(record, attribute) - end - end - - def record_value(record, attribute) - if attribute[:source] == "_subrecs" - if @query["output"]["format"] == "complex" - record.sub_records.collect do |sub_record| - target_attributes = resolve_attributes(attribute, sub_record) - complex_record(target_attributes, sub_record) - end - else - record.sub_records.collect do |sub_record| - target_attributes = resolve_attributes(attribute, sub_record) - simple_record(target_attributes, sub_record) - end - end - else - expression = attribute[:expression] - if expression - variable = attribute[:variable] - variable.value = record - expression.execute - else - value = record[attribute[:source]] - if value.is_a?(Groonga::Record) - value.record_id - else - value - end - end - end - end - - def resolve_attributes(attribute, record) - unless attribute[:target_attributes] - attribute[:target_attributes] = - normalize_target_attributes(attribute[:attributes], record.table) - end - return attribute[:target_attributes] - end - - def accessor_name?(source) - /\A[a-zA-Z\#@$_][a-zA-Z\d\#@$_\-.]*\z/ === source - end - - def normalize_target_attributes(attributes, domain = @result) - attributes.collect do |attribute| - if attribute.is_a?(String) - attribute = { - "source" => attribute, - } - end - source = attribute["source"] - if accessor_name?(source) - expression = nil - variable = nil - else - expression = Groonga::Expression.new(context: @context) - variable = expression.define_variable(domain: domain) - expression.parse(source, syntax: :script) - condition = expression.define_variable(name: "$condition", - reference: true) - condition.value = @condition - source = nil - end - { - label: attribute["label"] || attribute["source"], - source: source, - expression: expression, - variable: variable, - attributes: attribute["attributes"] - } - end - end - def log_tag "[#{Process.ppid}][#{Process.pid}] query_searcher" end -------------- next part -------------- HTML����������������������������... Descargar