Class: Typesensual::Index

Inherits:
Object
  • Object
show all
Includes:
StateHelpers
Defined in:
lib/typesensual/index.rb

Overview

Represents your index as a set of collections in Typesense. Manages Typesense aliases, but with some extra functionality for managing multiple environments and versions, and a nice DSL for defining your schema.

Examples:

Defining an index

class PostsIndex < Typesensual::Index
  # Optional, default is inferred from the class name
  index_name 'user_posts'

  schema do
    field 'text', type: 'string[]'
    field 'user', type: 'string', facet: true
  end
end

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.alias_nameString

The alias name for this index in the current environment

Returns:

  • (String)

    the alias name



57
58
59
# File 'lib/typesensual/index.rb', line 57

def self.alias_name
  [index_name, env].compact.join(':')
end

.ar_callbacksObject



163
164
165
# File 'lib/typesensual/index.rb', line 163

def self.ar_callbacks
  Typesensual::Callbacks.new(self)
end

.collectionCollection

Get the collection that the alias points to

Returns:

  • (Collection)

    the collection that the alias points to



97
98
99
# File 'lib/typesensual/index.rb', line 97

def self.collection
  @collection ||= Collection.new(alias_name)
end

.collection_for(version:) ⇒ Object



88
89
90
91
92
# File 'lib/typesensual/index.rb', line 88

def self.collection_for(version:)
  Typesensual.collections.find do |collection|
    collection.version == version
  end
end

.collection_name_for(version: Time.now.strftime('%s')) ⇒ String

Generate a new collection name for the given version

Parameters:

  • version (String) (defaults to: Time.now.strftime('%s'))

    the version to generate the collection name for

Returns:

  • (String)

    the generated collection name



65
66
67
# File 'lib/typesensual/index.rb', line 65

def self.collection_name_for(version: Time.now.strftime('%s'))
  "#{alias_name}@#{version}"
end

.collectionsArray<Collection>

Get the collections for this index

Returns:

  • (Array<Collection>)

    the collections that match the alias



82
83
84
85
86
# File 'lib/typesensual/index.rb', line 82

def self.collections
  Typesensual.collections.filter do |collection|
    collection.index_name == index_name
  end
end

.create!(version: Time.now.strftime('%s')) ⇒ Collection

Create a new collection for this index

Parameters:

  • version (String) (defaults to: Time.now.strftime('%s'))

    the version to create the collection for

Returns:



73
74
75
76
77
# File 'lib/typesensual/index.rb', line 73

def self.create!(version: Time.now.strftime('%s'))
  generated_name = collection_name_for(version: version)

  Collection.create!(@schema.to_h.merge('name' => generated_name))
end

.index_many(ids, collection: self.collection, batch_size: 100) ⇒ Object



151
152
153
154
155
156
# File 'lib/typesensual/index.rb', line 151

def self.index_many(ids, collection: self.collection, batch_size: 100)
  collection.insert_many!(
    new.enum_for(:index, ids),
    batch_size: batch_size
  )
end

.index_name(value) ⇒ void .index_nameString

Get or set the name for this index

Overloads:

  • .index_name(value) ⇒ void

    This method returns an undefined value.

    Explicitly set the index name

    Parameters:

    • value (String)

      the name to identify this index

  • .index_nameString

    Get the index name (either explicitly set or inferred from the class name)

    Returns:

    • (String)

      the name of this index



46
47
48
49
50
51
52
# File 'lib/typesensual/index.rb', line 46

def self.index_name(value = nil)
  if value
    @index_name = value
  else
    @index_name ||= name.underscore.sub(/_index$/, '')
  end
end

.index_one(id, collection: self.collection) ⇒ Object



135
136
137
138
139
# File 'lib/typesensual/index.rb', line 135

def self.index_one(id, collection: self.collection)
  new.index([id]) do |record|
    collection.insert_one!(record)
  end
end

.inherited(subclass) ⇒ Object



28
29
30
31
32
# File 'lib/typesensual/index.rb', line 28

def self.inherited(subclass)
  super
  # Copy the schema from the parent class to the subclass
  subclass.instance_variable_set(:@schema, @schema&.dup)
end

.reindex!(ids, collection: create!) ) ⇒ Object

Indexes the given records into a collection, then updates the alias to point to it.

Parameters:

  • records (Enumerable)

    the records to index

  • collection (Collection) (defaults to: create!) )

    the collection to index into, defaults to a new collection



129
130
131
132
133
# File 'lib/typesensual/index.rb', line 129

def self.reindex!(ids, collection: create!)
  index_many(ids, collection: collection)

  update_alias!(collection)
end

.remove_one(id, collection: self.collection) ⇒ Object



158
159
160
# File 'lib/typesensual/index.rb', line 158

def self.remove_one(id, collection: self.collection)
  collection.remove_one!(id)
end

.schema(&block) ⇒ Object

Define the schema for the collection

See Schema for more information



104
105
106
107
108
# File 'lib/typesensual/index.rb', line 104

def self.schema(&block)
  @schema ||= Typesensual::Schema.new
  @schema.instance_eval(&block) if block
  @schema
end

.update_alias!(name_or_collection) ⇒ Object

Updates the alias to point to the given collection name

Parameters:

  • name (String, Collection)

    the collection to point the alias to



113
114
115
116
117
118
119
120
121
# File 'lib/typesensual/index.rb', line 113

def self.update_alias!(name_or_collection)
  name = if name_or_collection.is_a?(Collection)
           name_or_collection.name
         else
           name_or_collection
         end

  client.aliases.upsert(alias_name, collection_name: name)
end

Instance Method Details

#index(ids) {|Hash| ... } ⇒ Object

The method to implement to index many records This method should yield successive records to index

Yields:

  • (Hash)

    a document to upsert in Typesense



145
146
147
148
149
# File 'lib/typesensual/index.rb', line 145

def index(ids)
  ids.each do |id|
    yield({ id: id })
  end
end