Module: Spectre::Searchable::ClassMethods

Defined in:
lib/spectre/searchable.rb

Instance Method Summary collapse

Instance Method Details

#configure_spectre_result_fields(fields) ⇒ Object

Configure the default fields to include in the search results.



31
32
33
# File 'lib/spectre/searchable.rb', line 31

def configure_spectre_result_fields(fields)
  @result_fields = fields
end

#configure_spectre_search_index(index) ⇒ Object

Configure the index to be used for the vector search.



24
25
26
# File 'lib/spectre/searchable.rb', line 24

def configure_spectre_search_index(index)
  @search_index = index
end

#configure_spectre_search_path(path) ⇒ Object

Configure the path to the embedding field for the vector search.



17
18
19
# File 'lib/spectre/searchable.rb', line 17

def configure_spectre_search_path(path)
  @search_path = path
end

#result_fieldsHash?

Provide access to the configured result fields.



52
53
54
# File 'lib/spectre/searchable.rb', line 52

def result_fields
  @result_fields
end

#search_indexString

Provide access to the configured search index.



45
46
47
# File 'lib/spectre/searchable.rb', line 45

def search_index
  @search_index || 'vector_index'  # Default to 'vector_index' if not configured
end

#search_pathString

Provide access to the configured search path.



38
39
40
# File 'lib/spectre/searchable.rb', line 38

def search_path
  @search_path || 'embedding'  # Default to 'embedding' if not configured
end

#vector_search(query, limit: 5, additional_scopes: [], custom_result_fields: nil) ⇒ Array<Hash>

Searches based on a query string by first embedding the query.

Examples:

Basic search with configured result fields

results = Model.vector_search("What is AI?")

Search with custom result fields

results = Model.vector_search(
  "What is AI?",
  limit: 10,
  custom_result_fields: { "some_additional_field": 1, "another_field": 1 }
)

Search with additional filtering using scopes

results = Model.vector_search(
  "What is AI?",
  limit: 10,
  additional_scopes: [{ "$match": { "some_field": "some_value" } }]
)

Combining custom result fields and additional scopes

results = Model.vector_search(
  "What is AI?",
  limit: 10,
  additional_scopes: [{ "$match": { "some_field": "some_value" } }],
  custom_result_fields: { "some_additional_field": 1, "another_field": 1 }
)


90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/spectre/searchable.rb', line 90

def vector_search(query, limit: 5, additional_scopes: [], custom_result_fields: nil)
  # Check if the query is a string (needs embedding) or an array (already embedded)
  embedded_query = if query.is_a?(String)
                     Spectre.provider_module::Embeddings.create(query)
                   elsif query.is_a?(Array) && query.all? { |e| e.is_a?(Float) }
                     query
                   else
                     raise ArgumentError, "Query must be a String or an Array of Floats"
                   end

  # Build the MongoDB aggregation pipeline
  pipeline = [
    {
      "$vectorSearch": {
        "queryVector": embedded_query,
        "path": search_path,
        "numCandidates": 100,
        "limit": limit,
        "index": search_index
      }
    }
  ]

  # Add any additional scopes provided
  pipeline.concat(additional_scopes) if additional_scopes.any?

  # Determine the fields to include in the results
  fields_to_project = custom_result_fields || result_fields || {}
  fields_to_project["score"] = { "$meta": "vectorSearchScore" }

  # Add the project stage with the fields to project
  pipeline << { "$project": fields_to_project }

  self.collection.aggregate(pipeline).to_a
end