def search(expression, options={})
      opts          = {:sort_decending => false}.merge(options)
      @query_parser ||= QueryParser.new(self)
      query         = @query_parser.parse(expression)

      # If we do not have a valid query we return an empty result set
      return Resultset.new(nil, opts) unless query

      start = Time.now

      enquiry        = Xapian::Enquire.new(reader)
      enquiry.query  = query
      sort_indices   = opts.delete :sort_indices
      sort_decending = opts.delete :sort_decending
      order          = opts.delete :order
      raise ArgumentError.new "you can't use sort_indices and order, only one of them" if sort_indices && order

      if order
        sort_indices = order.map{ |attr_name| XapianDb::DocumentBlueprint.value_number_for attr_name.to_sym }
      end

      sorter = Xapian::MultiValueKeyMaker.new
      if sort_indices
        sort_indices.each { |index| sorter.add_value index }
        enquiry.set_sort_by_key_then_relevance(sorter, sort_decending)
      else
        sorter.add_value DocumentBlueprint.value_number_for(:natural_sort_order)
        enquiry.set_sort_by_relevance_then_key sorter, false
      end

      opts[:spelling_suggestion] = @query_parser.spelling_suggestion
      opts[:db_size]             = self.size

      retries = 0
      begin
        result = Resultset.new(enquiry, opts)
      rescue IOError => ex
        raise unless ex.message =~ /DatabaseModifiedError: /
        raise if retries >= 5
        sleep 0.1
        retries += 1
        Rails.logger.warn "XapianDb: DatabaseModifiedError, retry #{retries}" if defined?(Rails)
        @reader.reopen
        retry
      end

      Rails.logger.debug "XapianDb search (#{(Time.now - start) * 1000}ms) #{expression}" if defined?(Rails)
      result
    end
def search(expression, options={})
      opts          = {:sort_decending => false}.merge(options)
      @query_parser ||= QueryParser.new(self)
      query         = @query_parser.parse(expression)

      # If we do not have a valid query we return an empty result set
      return Resultset.new(nil, opts) unless query

      start = Time.now

      enquiry        = Xapian::Enquire.new(reader)
      enquiry.query  = query
      sort_indices   = opts.delete :sort_indices
      sort_decending = opts.delete :sort_decending
      order          = opts.delete :order
      raise ArgumentError.new "you can't use sort_indices and order, only one of them" if sort_indices && order

      if order
        sort_indices = order.map{ |attr_name| XapianDb::DocumentBlueprint.value_number_for attr_name.to_sym }
      end

      sorter = Xapian::MultiValueKeyMaker.new
      if sort_indices
        sort_indices.each { |index| sorter.add_value index }
        enquiry.set_sort_by_key_then_relevance(sorter, sort_decending)
      else
        sorter.add_value DocumentBlueprint.value_number_for(:natural_sort_order)
        enquiry.set_sort_by_relevance_then_key sorter, false
      end

      opts[:spelling_suggestion] = @query_parser.spelling_suggestion
      opts[:db_size]             = self.size

      retries = 0
      begin
        result = Resultset.new(enquiry, opts)
      rescue IOError => ex
        raise unless ex.message =~ /DatabaseModifiedError: /
        raise if retries >= 5
        sleep 0.1
        retries += 1
        Rails.logger.warn "XapianDb: DatabaseModifiedError, retry #{retries}" if defined?(Rails)
        @reader.reopen
        retry
      end

      Rails.logger.debug "XapianDb search (#{(Time.now - start) * 1000}ms) #{expression}" if defined?(Rails)
      result
    end
Perform a search
 @param [String] expression A valid search expression.
 @param [Hash] options
 @option options [Integer] :per_page How many docs per page?
 @option options [Array<Integer>] :sort_indices (nil) An array of attribute indices to sort by. This
   option is used internally by the search method implemented on configured classes. Do not use it
   directly unless you know what you do
 @option options [Boolean] :sort_decending (false) Reverse the sort order?
 @example Simple Query
   resultset = db.search("foo")
 @example Wildcard Query
   resultset = db.search("fo*")
 @example Boolean Query
   resultset = db.search("foo or baz")
 @example Field Query
   resultset = db.search("name:foo")
 @return [XapianDb::Resultset] The resultset