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.

Parameters:

  • fields (Hash)

    The fields to include in the results, with their MongoDB projection configuration.



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.

Parameters:

  • index (String)

    The name of the vector index.



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.

Parameters:

  • path (String)

    The path to the embedding field.



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.

Returns:

  • (Hash, nil)

    The configured result fields, or nil if not configured.



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.

Returns:

  • (String)

    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.

Returns:

  • (String)

    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 }
)

Parameters:

  • query (String)

    The text query to embed and search for.

  • limit (Integer) (defaults to: 5)

    The maximum number of results to return (default: 5).

  • additional_scopes (Array<Hash>) (defaults to: [])

    Additional MongoDB aggregation stages to filter or modify results.

  • custom_result_fields (Hash, nil) (defaults to: nil)

    Custom fields to include in the search results, overriding the default.

Returns:

  • (Array<Hash>)

    The search results, including the configured fields and score.



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