Class: ActsAsXapian::Similar

Inherits:
QueryBase show all
Defined in:
lib/acts_as_xapian/similar.rb

Overview

Search for models which contain theimportant terms taken from a specified list of models. i.e. Use to find documents similar to one (or more) documents, or use to refine searches.

Instance Attribute Summary collapse

Attributes inherited from QueryBase

#cached_results, #limit, #offset, #query, #runtime

Instance Method Summary collapse

Methods inherited from QueryBase

#description, #matches, #matches_estimated, #results, #spelling_correction

Constructor Details

#initialize(model_classes, query_models, options = {}) ⇒ Similar

model_classes - model classes to search within, e.g. [PublicBody, User] query_models - list of models you want to find things similar to



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/acts_as_xapian/similar.rb', line 11

def initialize(model_classes, query_models, options = {})
  self.initialize_db(model_classes)

  self.runtime += Benchmark::realtime do
    # Case of an array, searching for models similar to those models in the array
    self.query_models = query_models

    # Find the documents by their unique term
    input_models_query = Xapian::Query.new(Xapian::Query::OP_OR, query_models.map {|m| "I#{m.xapian_document_term}" })
    begin
      @index.enquire.query = input_models_query

      # Get set of relevant terms for those documents
      selection = Xapian::RSet.new()
      @index.enquire.mset(0, 100, 100).matches.each {|m| selection.add_document(m.docid) } # XXX so this whole method will only work with 100 docs

      # Bit weird that the function to make esets is part of the enquire
      # object. This explains what exactly it does, which is to exclude
      # terms in the existing query.
      # http://thread.gmane.org/gmane.comp.search.xapian.general/3673/focus=3681
      #
      # Do main search for them
      self.important_terms = @index.enquire.eset(40, selection).terms.map {|e| e.name }
    rescue IOError => e
      if @retried.nil? && /DatabaseModifiedError/.match(e.message.to_s)
        @retried = true
        @index.reset_enquire!
        retry
      end
      raise e
    end

    similar_query = Xapian::Query.new(Xapian::Query::OP_OR, self.important_terms)
    # Exclude original
    combined_query = Xapian::Query.new(Xapian::Query::OP_AND_NOT, similar_query, input_models_query)

    # Restrain to model classes
    model_query = Xapian::Query.new(Xapian::Query::OP_OR, model_classes.map {|mc| "M#{mc}" })
    self.query = Xapian::Query.new(Xapian::Query::OP_AND, model_query, combined_query)
  end

  # Call base class constructor
  self.initialize_query(options)
end

Instance Attribute Details

#important_termsObject

Returns the value of attribute important_terms.



7
8
9
# File 'lib/acts_as_xapian/similar.rb', line 7

def important_terms
  @important_terms
end

#query_modelsObject

Returns the value of attribute query_models.



6
7
8
# File 'lib/acts_as_xapian/similar.rb', line 6

def query_models
  @query_models
end

Instance Method Details

#log_descriptionObject

Text for lines in log file



57
58
59
# File 'lib/acts_as_xapian/similar.rb', line 57

def log_description
  "Similar: #{self.query_models}"
end