Class: Litesearch::Index

Inherits:
Object
  • Object
show all
Defined in:
lib/litestack/litesearch.rb,
lib/litestack/litesearch/index.rb

Constant Summary collapse

DEFAULT_SEARCH_OPTIONS =
{limit: 25, offset: 0}

Instance Method Summary collapse

Constructor Details

#initialize(db, name) ⇒ Index

Returns a new instance of Index.



7
8
9
10
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
# File 'lib/litestack/litesearch/index.rb', line 7

def initialize(db, name)
  @db = db # this index instance will always belong to this db instance
  @stmts = {}
  name = name.to_s.downcase.to_sym
  # if in the db then put in cache and return if no schema is given
  # if a schema is given then compare the new and the existing schema
  # if they are the same put in cache and return
  # if they differ only in weights then set the new weights, update the schema, put in cache and return
  # if they differ in fields (added/removed/renamed) then update the structure, then rebuild if auto-rebuild is on
  # if they differ in tokenizer then rebuild if auto-rebuild is on (error otherwise)
  # if they differ in both then update the structure and rebuild if auto-rebuild is on (error otherwise)
  load_index(name) if exists?(name)

  if block_given?
    schema = Litesearch::Schema.new
    schema.schema[:name] = name
    yield schema
    schema.post_init
    # now that we have a schema object we need to check if we need to create or modify and existing index
    if @db.transaction_active?
      if exists?(name)
        load_index(name)
        do_modify(schema)
      else
        do_create(schema)
      end
      prepare_statements
    else
      @db.transaction(:immediate) do
        if exists?(name)
          load_index(name)
          do_modify(schema)
        else
          do_create(schema)
        end
        prepare_statements
      end
    end
  elsif exists?(name)
    load_index(name)
    prepare_statements
  # an index already exists, load it from the database and return the index instance to the caller
  else
    raise "index does not exist and no schema was supplied"
  end
end

Instance Method Details

#add(document) ⇒ Object



80
81
82
83
# File 'lib/litestack/litesearch/index.rb', line 80

def add(document)
  @stmts[:insert].execute!(document)
  @db.last_insert_row_id
end

#clear!Object



119
120
121
# File 'lib/litestack/litesearch/index.rb', line 119

def clear!
  @stmts[:delete_all].execute!(id)
end

#count(term = nil) ⇒ Object



89
90
91
92
93
94
95
# File 'lib/litestack/litesearch/index.rb', line 89

def count(term = nil)
  if term
    @stmts[:count].execute!(term)[0][0]
  else
    @stmts[:count_all].execute![0][0]
  end
end

#drop!Object



123
124
125
126
127
128
129
130
131
# File 'lib/litestack/litesearch/index.rb', line 123

def drop!
  if @schema.get(:type) == :backed
    @db.execute_batch(@schema.sql_for(:drop_primary_triggers))
    if @schema.sql_for(:create_secondary_triggers)
      @db.execute_batch(@schema.sql_for(:drop_secondary_triggers))
    end
  end
  @db.execute(@schema.sql_for(:drop))
end

#load_index(name) ⇒ Object



54
55
56
57
58
59
60
61
62
63
# File 'lib/litestack/litesearch/index.rb', line 54

def load_index(name)
  # we cannot use get_config_value here since the schema object is not created yet, should we allow something here?
  @schema = begin
    Litesearch::Schema.new(Oj.load(@db.get_first_value("SELECT v from #{name}_config where k = ?", :litesearch_schema.to_s)))
  rescue
    nil
  end
  raise "index configuration not found, either corrupted or not a litesearch index!" if @schema.nil?
  self
end

#modify {|schema| ... } ⇒ Object

Yields:

  • (schema)


65
66
67
68
69
70
# File 'lib/litestack/litesearch/index.rb', line 65

def modify
  schema = Litesearch::Schema.new
  yield schema
  schema.schema[:name] = @schema.schema[:name]
  do_modify(schema)
end

#rebuild!Object



72
73
74
75
76
77
78
# File 'lib/litestack/litesearch/index.rb', line 72

def rebuild!
  if @db.transaction_active?
    do_rebuild
  else
    @db.transaction(:immediate) { do_rebuild }
  end
end

#remove(id) ⇒ Object



85
86
87
# File 'lib/litestack/litesearch/index.rb', line 85

def remove(id)
  @stmts[:delete].execute!(id)
end

#search(term, options = {}) ⇒ Object

search options include limit: how many records to return offset: start from which record



100
101
102
103
104
# File 'lib/litestack/litesearch/index.rb', line 100

def search(term, options = {})
  options = DEFAULT_SEARCH_OPTIONS.merge(options)
  rs = @stmts[:search].execute(term, options[:limit], options[:offset])
  generate_results(rs)
end

#similar(id, limit = 10) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/litestack/litesearch/index.rb', line 106

def similar(id, limit = 10)
  #   pp term = @db.execute(@schema.sql_for(:similarity_query), id)
  rs = if @schema.schema[:tokenizer] == :trigram
    # just use the normal similarity approach for now
    # need to recondisder that for trigram indexes later
    @stmts[:similar].execute(id, limit) # standard:disable Style/IdenticalConditionalBranches
  else
    @stmts[:similar].execute(id, limit) # standard:disable Style/IdenticalConditionalBranches
  end

  generate_results(rs)
end