# encoding: utf-8
module XapianDb
module Adapters
# base class for all adapters.
# This adapter does the following:
# - adds the class method search(expression)
to an indexed class
# @author Gernot Kogler
class BaseAdapter
class << self
# Implement the class helper methods
# @param [Class] klass The class to add the helper methods to
def add_class_helper_methods_to(klass)
klass.class_eval do
# Add a method to search models of this class
# Options:
# - :order (Array) Accepts an array of attribute names for sorting
# - :sort_decending (Boolean) Allows to reverse the sorting
define_singleton_method(:search) do |expression, options={}|
# return an empty search if no search expression is given
return XapianDb.database.search(nil) if expression.nil? || expression.strip.empty?
options = {:sort_decending => false}.merge options
class_scope = "indexed_class:#{klass.name.downcase}"
if options[:order]
attr_names = [options[:order]].flatten
blueprint = XapianDb::DocumentBlueprint.blueprint_for klass
sort_indices = attr_names.map {|attr_name| blueprint.value_index_for(attr_name)}
options[:sort_indices] = attr_names.map {|attr_name| blueprint.value_index_for(attr_name)}
end
result = XapianDb.database.search "#{class_scope} and (#{expression})", options
# Remove the class scope from the spelling suggestion (if any)
unless result.spelling_suggestion.empty?
scope_length = "#{class_scope} and (".size
result.spelling_suggestion = result.spelling_suggestion.slice scope_length..-2
end
result
end
# Add a method to search atribute facets of this class
define_singleton_method(:facets) do |attr_name, expression|
# return an empty hash if no search expression is given
return {} if expression.nil? || expression.strip.empty?
class_scope = "indexed_class:#{klass.name.downcase}"
blueprint = XapianDb::DocumentBlueprint.blueprint_for klass
value_index = blueprint.value_index_for attr_name.to_sym
query_parser = QueryParser.new(XapianDb.database)
query = query_parser.parse("#{class_scope} and (#{expression})")
enquiry = Xapian::Enquire.new(XapianDb.database.reader)
enquiry.query = query
enquiry.collapse_key = value_index
facets = {}
enquiry.mset(0, XapianDb.database.size).matches.each do |match|
facet_value = YAML::load match.document.values[value_index].value
# We must add 1 to the collapse_count since collapse_count means
# "how many other matches are there?"
facets[facet_value] = match.collapse_count + 1
end
facets
end
end
end
end
end
end
end