Documentation
¶
Overview ¶
Package cassandra exposes Apache Cassandra 5.0+ vector support through the Core vector-store capability interfaces. Documents live in a regular CQL table with a `vector<float, N>` column; filterable metadata keys must be declared as typed columns (Cassandra has no JSON-path operator), each indexed via a Storage Attached Index (SAI). Documents containing media are rejected before indexing I/O because this adapter persists document text and metadata only.
Metadata model. A document's metadata of record is the JSON in StoreConfig.MetadataColumn, which carries no SAI index. The declared typed columns are the filterable projection of that record. CQL reaches a metadata key only as a declared column, so writing only those columns dropped every other key with no error and no way to get it back, and reading them back returned a document without those keys. Reading the record instead makes the round trip exact and keeps undeclared keys; declaring a column is what makes a key filterable, not what makes it stored.
Requirements: Apache Cassandra 5.0+ or compatible (DataStax Astra DB / DataStax Enterprise). Vector + SAI both arrived together in 5.0. The store uses gocql v1.x.
Similarity functions — recorded in the SAI index definition at creation time:
- SimilarityCosine — cosine similarity (default)
- SimilarityDotProduct — inner product
- SimilarityEuclidean — Euclidean distance
Scores. Apache Cassandra documents the similarity_cosine, similarity_dot_product and similarity_euclidean signatures but not the range of what they return, so the store takes the value as a relevance score already on Core's scale and clamps it. That is an assumption about an undocumented property rather than a mapping: if a server reports a value outside the range, the clamp keeps Cassandra's ordering only below the bound. similarity_dot_product also assumes L2-normalized vectors — Cassandra does not normalize for it — so a non-normalized embedding makes the value meaningless before it ever reaches a score.
Vector binding caveat. gocql v1.x has no first-class `vector<float, N>` codec, so the store inlines vectors as CQL literals (`[v1, v2, ...]`) into the SQL. Cassandra accepts that form for both INSERT and ORDER BY ANN OF. The other parameters flow through normal `?` placeholders.
Filter constraints. CQL on regular columns doesn't support `OR` or standalone `NOT`; the visitor rejects them with a clear error. `IN` is fine and binds as a typed slice. Every filterable metadata key must exist as a typed column on the table, declared via StoreConfig.MetadataColumns entries with their CQL type (text / int / boolean / double / …).
Filter-based DELETE. Cassandra forbids deleting by a non-PK predicate. The store works around it by SELECT-ing matching ids first then issuing per-row DELETEs.
Partial writes. Neither Index nor DeleteWhere is atomic: both walk their rows one statement at a time, so a failure leaves the statements already executed applied. The returned error names the id that failed, and the operation is safe to repeat because both statements are idempotent per row.
Filter limits come from CQL, not from this store: a WHERE clause supports neither OR nor a standalone NOT, has no IS NULL and no LIKE on a metadata column, and reaches a metadata key only as a declared column — so an indexed or nested key cannot be filtered either.
See https://cassandra.apache.org/doc/latest/cassandra/vector-search/ for the official reference.
Index ¶
- Constants
- type MetadataColumn
- type SimilarityFunction
- type Store
- func (s *Store) DeleteIDs(ctx context.Context, ids []string) (err error)
- func (s *Store) DeleteWhere(ctx context.Context, expr filter.Predicate) (err error)
- func (s *Store) Index(ctx context.Context, request *vectorstore.IndexRequest) (err error)
- func (s *Store) Search(ctx context.Context, req *vectorstore.SearchRequest) (response *vectorstore.SearchResponse, err error)
- type StoreConfig
Constants ¶
const ( DefaultKeyspaceName = "scope" DefaultTableName = "vector_store" DefaultIDColumn = "id" DefaultContentColumn = "content" DefaultMetadataColumn = "metadata" DefaultEmbeddingColumn = "embedding" DefaultSimilarity = SimilarityCosine )
Exported defaults keep constructor behavior visible and overridable.
const Provider = "Cassandra"
Provider is the stable backend name for host-side attribution.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type MetadataColumn ¶
type MetadataColumn struct {
// Name is the column identifier on the underlying table.
Name string
// CQLType is the column data type as written in CREATE TABLE
// (e.g. "text", "int", "boolean", "double").
CQLType string
}
MetadataColumn declares a custom metadata column that the store indexes for filtering. Cassandra has no JSON-path operator, so each filterable metadata key must be a typed column on the table.
type SimilarityFunction ¶
type SimilarityFunction string
SimilarityFunction picks the function name used by the similarity_<func> built-in. The chosen value is recorded in the SAI index definition at creation time.
const ( // SimilarityCosine — cosine similarity. Default. SimilarityCosine SimilarityFunction = "cosine" // SimilarityDotProduct — dot product. SimilarityDotProduct SimilarityFunction = "dot_product" // SimilarityEuclidean — Euclidean (L2) distance, mapped to a // similarity score by Cassandra itself. SimilarityEuclidean SimilarityFunction = "euclidean" )
func (SimilarityFunction) String ¶
func (s SimilarityFunction) String() string
func (SimilarityFunction) Valid ¶
func (s SimilarityFunction) Valid() bool
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store implements vector-store capabilities with Cassandra 5.0+ VECTOR columns and SAI indexes.
func NewStore ¶
func NewStore(ctx context.Context, config StoreConfig) (*Store, error)
NewStore performs schema setup during construction, which is why it takes a context: a store returned before its keyspace table exists would fail on the first index rather than at wiring, where the misconfiguration actually is.
func (*Store) DeleteIDs ¶
DeleteIDs removes rows by primary key. Because the id column is the partition key, CQL allows a single DELETE with an IN list over it: `DELETE FROM <table> WHERE <idCol> IN (?, ?, ...)`. An empty slice is a no-op; unknown ids are silently ignored (idempotent). Implements vectorstore.IDDeleter.
func (*Store) DeleteWhere ¶
func (*Store) Index ¶
func (s *Store) Index(ctx context.Context, request *vectorstore.IndexRequest) (err error)
Index embeds documents and inserts them.
func (*Store) Search ¶
func (s *Store) Search(ctx context.Context, req *vectorstore.SearchRequest) (response *vectorstore.SearchResponse, err error)
Search runs an ANN query using the configured similarity function.
type StoreConfig ¶
type StoreConfig struct {
// Session is the gocql session. Required.
Session *gocql.Session
// KeyspaceName is the keyspace that holds the vector table.
// Optional: defaults to [DefaultKeyspaceName].
KeyspaceName string
// TableName is the table that stores documents and their
// embeddings. Optional: defaults to [DefaultTableName].
TableName string
// IDColumn / ContentColumn / EmbeddingColumn / MetadataColumn —
// override the column names of the generated schema. Each
// defaults to its respective Default* constant when empty.
IDColumn string
ContentColumn string
EmbeddingColumn string
// MetadataColumn is the text column that holds a document's metadata as
// JSON. It carries no SAI index because it is the record rather than a
// filterable projection of it.
//
// CQL reaches a metadata key only as a declared column, so writing only
// the columns in MetadataColumns dropped every other key with no error and
// no way to get it back. This column keeps the document whole; the typed
// columns below stay the filterable projection of it.
MetadataColumn string
// MetadataColumns enumerates the filterable metadata keys. Each
// becomes a typed column on the table and (under
// InitializeSchema) an SAI index. The optional [DocumentMetadata]
// helpers may populate these from the Document.Metadata map.
MetadataColumns []MetadataColumn
// EmbeddingModel produces vectors for the documents. Required.
EmbeddingModel embedding.Model
// DocumentBatcher batches documents before insertion. Required.
DocumentBatcher vectorstore.Batcher
// Dimensions sets the VECTOR column width, and is required when
// InitializeSchema is true: the width is part of the column type, and
// nothing here can read it off a table that does not exist yet.
Dimensions int
// Similarity selects the vector similarity function. Optional:
// defaults to [SimilarityCosine].
Similarity SimilarityFunction
// InitializeSchema, when true, creates the keyspace, table, and
// SAI vector index if they don't already exist.
InitializeSchema bool
// KeyspaceReplication is the replication clause used when
// InitializeSchema creates the keyspace — e.g.
// "{'class': 'SimpleStrategy', 'replication_factor': 1}".
// Optional: defaults to a single-replica SimpleStrategy.
KeyspaceReplication string
}
StoreConfig contains configuration options for the Cassandra vector store.
func (StoreConfig) Validate ¶
func (s StoreConfig) Validate() error