class XapianDb::QueryParser

Parse a query expression and create a xapian query object @author Gernot Kogler

Attributes

spelling_suggestion[R]

The spelling corrected query (if a language is configured) @return [String]

Public Class Methods

new(database) click to toggle source

Constructor @param [XapianDb::Database] database The database to query

   # File lib/xapian_db/query_parser.rb
15 def initialize(database)
16   @db = database
17 
18   # Set the parser options
19   @query_flags = 0
20   XapianDb::Config.query_flags.each { |flag| @query_flags |= flag }
21 end

Public Instance Methods

parse(expression) click to toggle source

Parse an expression @return [Xapian::Query] The query object (see xapian.org/docs/apidoc/html/classXapian_1_1Query.html)

   # File lib/xapian_db/query_parser.rb
25 def parse(expression)
26   return nil if expression.nil? || expression.strip.empty?
27   parser            = Xapian::QueryParser.new
28   parser.database   = @db.reader
29   parser.default_op = Xapian::Query::OP_AND # Could be made configurable
30   if XapianDb::Config.stemmer
31     parser.stemmer           = XapianDb::Config.stemmer
32     parser.stemming_strategy = Xapian::QueryParser::STEM_SOME
33     parser.stopper           = XapianDb::Config.stopper
34   end
35   max_expansion = XapianDb::Config.set_max_expansion
36   parser.set_max_expansion(max_expansion, Xapian::Query::WILDCARD_LIMIT_MOST_FREQUENT) if max_expansion
37 
38   # Add the searchable prefixes to allow searches by field
39   # (like "name:Kogler")
40   processors = [] # The reason for having a seemingly useless "processors" array is as follows:
41   # We need to add a reference to the generated Xapian::XYValueRangeProcessor objects to the scope that calls parser.parse_query.
42   # If we don't, the Ruby GC will often garbage collect the generated objects before parser.parse_query can be called,
43   # which would free the memory of the corresponding C++ objects and result in segmentation faults upon calling parse_query.
44   XapianDb::DocumentBlueprint.searchable_prefixes.each do |prefix|
45     parser.add_prefix(prefix.to_s.downcase, "X#{prefix.to_s.upcase}")
46     type_info = XapianDb::DocumentBlueprint.type_info_for(prefix)
47     next if type_info.nil? || type_info == :generic
48     value_number = XapianDb::DocumentBlueprint.value_number_for(prefix)
49     case type_info
50       when :date
51         processor = Xapian::DateValueRangeProcessor.new(value_number, "#{prefix}:")
52         processors << processor
53         parser.add_valuerangeprocessor(processor)
54       when :number
55         processor = Xapian::NumberValueRangeProcessor.new(value_number, "#{prefix}:")
56         processors << processor
57         parser.add_valuerangeprocessor(processor)
58       when :string
59         processor = Xapian::StringValueRangeProcessor.new(value_number, "#{prefix}:")
60         processors << processor
61         parser.add_valuerangeprocessor(processor)
62     end
63   end
64   query = parser.parse_query(expression, @query_flags)
65   @spelling_suggestion = parser.get_corrected_query_string.force_encoding("UTF-8")
66   @spelling_suggestion = nil if @spelling_suggestion.empty?
67   query
68 end