redis

package module
v0.18.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package redis exposes Redis Stack's RediSearch module through the Core vector-store capability interfaces. Documents are stored as Redis HASHes keyed at `<KeyPrefix><id>`; an FT.CREATE-defined index registers the vector field plus any pre-declared metadata fields. Documents containing media are rejected before indexing I/O because this adapter persists document text and metadata only.

Requirements: Redis Stack (or Redis OSS 8.0+ with the search module) — RediSearch is mandatory. RedisJSON is NOT required; the store deliberately uses HASH storage to keep the dependency surface minimal.

Distance metrics: DistanceCosine / DistanceL2 / DistanceIP. Vector index algorithm: AlgorithmHNSW (default) / AlgorithmFlat.

Metadata model. Every filterable metadata key MUST be declared in StoreConfig.MetadataFields up-front with its RediSearch type — FieldTag (exact match), FieldNumeric (range queries), or FieldText (full-text). Filters against undeclared fields fail fast via [ErrUnknownMetadataField] (rather than reaching Redis and silently producing zero hits).

A document's metadata of record is the JSON in StoreConfig.MetadataJSONField, which is not part of the index schema. The declared fields are the index projection of that record: RediSearch indexes a HASH field's text as its declared type, so a declared field has to hold the value in the form the index expects and cannot also carry the value's type. Reading metadata back from those fields turned a number into a float64 and everything else into a string, and an undeclared key had no field to read at all, so a search returned a document that differed from the one that was written. Reading the record instead makes the round trip exact and keeps undeclared keys, and the projection no longer has to be reversible.

Query path. The filter visitor emits RediSearch syntax — TAG `@f:{v}`, NUMERIC `@f:[low high]`, TEXT `@f:(v)`. Vector retrieval runs FT.SEARCH with the hybrid syntax `(<filter>)=>[KNN K @embedding $vec AS distance]`, passing the binary FLOAT32 little-endian vector through PARAMS.

Result completeness. RediSearch bounds every query with TIMEOUT and its default ON_TIMEOUT policy answers successfully with the hits gathered so far, reporting the truncation as a warning. Search and filtered deletion reject a warned result, and deletion re-queries until a page comes back empty rather than reading a short page as an exhausted match set.

Null tests are refused. A RediSearch index has no predicate for a field that was never written — an unindexed field is simply absent from the inverted index — so an IS NULL filter fails rather than being approximated.

Existing index. The index is verified whenever it is found, whatever InitializeSchema says, because that flag answers whether a missing index may be created and not whether the one found is the right one — and the second question matters most for an index provisioned out of band. An index that is neither found nor creatable fails construction rather than every later request. Existence was previously taken for agreement: search converts RediSearch's distance into a Score using the configured metric, so an index built with L2 while the config says COSINE returned scores that were wrong rather than absent — nothing failed, the ranking was silently mis-scaled. FT.INFO now supplies the vector attribute's metric and dimension, and a mismatch fails construction with ErrIncompatibleIndex, where the misconfiguration is.

Field names. Every configured field name is written into the RediSearch query language as text — FT.CREATE declares it and a filter emits it as `@name` — and RediSearch cannot quote a field name, so construction requires each to be a dot-separated path of plain identifiers. The dots are allowed because a RediSearch schema is flat: a nested metadata key is declared as a dotted field name, and that is the only way to filter one. A filter can still only reference a declared field, so a key chosen at query time never reaches the query language unchecked.

See https://redis.io/docs/latest/develop/interact/search-and-query/ for the RediSearch reference.

Index

Constants

View Source
const (
	DefaultIndexName         = "scope-vector-index"
	DefaultKeyPrefix         = "embedding:"
	DefaultContentField      = "content"
	DefaultEmbeddingField    = "embedding"
	DefaultMetadataJSONField = "metadata_json"
	DefaultMetadataPrefix    = "" // empty: metadata keys land at top level of the HASH
	DefaultDistanceMetric    = DistanceCosine
	DefaultIndexAlgorithm    = AlgorithmHNSW
	DefaultHNSWM             = 16
	DefaultHNSWEFConstruct   = 200
	DefaultHNSWEFRuntime     = 10
)

Exported defaults keep constructor behavior visible and overridable.

View Source
const Provider = "Redis"

Provider is the stable backend name for host-side attribution.

Variables

View Source
var ErrIncompatibleIndex = errors.New("redis: existing index is incompatible")

ErrIncompatibleIndex reports an existing index whose vector field does not match the configuration this store scores against.

Functions

This section is empty.

Types

type DistanceMetric

type DistanceMetric string

DistanceMetric selects the similarity function used by the RediSearch vector index.

const (
	// DistanceCosine — cosine distance, range [0, 2]. The store
	// transforms it into a [0, 1] similarity score where higher is
	// more similar.
	DistanceCosine DistanceMetric = "COSINE"

	// DistanceL2 — Euclidean distance, range [0, ∞).
	DistanceL2 DistanceMetric = "L2"

	// DistanceIP — inner product. RediSearch returns the inner
	// product itself; the store maps it onto [0, 1] for unit-norm
	// vectors via (ip+1)/2.
	DistanceIP DistanceMetric = "IP"
)

func (DistanceMetric) String

func (d DistanceMetric) String() string

func (DistanceMetric) Valid

func (d DistanceMetric) Valid() bool

type IndexAlgorithm

type IndexAlgorithm string

IndexAlgorithm selects the RediSearch vector indexing algorithm.

const (
	// AlgorithmHNSW — hierarchical navigable small-world graph.
	// Default; best query performance.
	AlgorithmHNSW IndexAlgorithm = "HNSW"

	// AlgorithmFlat — exhaustive (brute-force) search. Useful for
	// small collections where build / memory cost matters more than
	// query latency.
	AlgorithmFlat IndexAlgorithm = "FLAT"
)

func (IndexAlgorithm) String

func (i IndexAlgorithm) String() string

func (IndexAlgorithm) Valid

func (i IndexAlgorithm) Valid() bool

type MetadataField

type MetadataField struct {
	// Name is the HASH field / JSON key that holds the value.
	Name string

	// Type controls the RediSearch index field type. See
	// [FieldTag] / [FieldText] / [FieldNumeric].
	Type MetadataFieldType

	// Sortable, when true, marks the field SORTABLE in the schema.
	Sortable bool
}

MetadataField declares one filterable metadata key. the framework's builder calls this a "MetadataField".

func (MetadataField) Validate

func (m MetadataField) Validate() error

type MetadataFieldType

type MetadataFieldType string

MetadataFieldType names the RediSearch schema field types the store understands. Callers declare these up-front so the filter visitor can validate field names and pick the right query syntax.

const (
	// FieldTag — RediSearch TAG field. Exact-match on categorical
	// data; supports IN / != via "|" join and "-" prefix.
	FieldTag MetadataFieldType = "TAG"

	// FieldText — full-text indexed field.
	FieldText MetadataFieldType = "TEXT"

	// FieldNumeric — numeric range field.
	FieldNumeric MetadataFieldType = "NUMERIC"
)

func (MetadataFieldType) String

func (m MetadataFieldType) String() string

func (MetadataFieldType) Valid

func (m MetadataFieldType) Valid() bool

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is a Redis-backed implementation of the vectorstore capability interfaces. It stores documents as Redis HASHes and queries them through RediSearch vector + metadata 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 search index exists would fail on the first index rather than at wiring, where the misconfiguration actually is.

func (*Store) DeleteIDs

func (s *Store) DeleteIDs(ctx context.Context, ids []string) (err error)

DeleteIDs removes documents by id, resolving each to its HASH key `<KeyPrefix><id>` and issuing a single DEL. An empty slice is a no-op; unknown ids are silently ignored (idempotent). Implements vectorstore.IDDeleter.

func (*Store) DeleteWhere

func (s *Store) DeleteWhere(ctx context.Context, expr filter.Predicate) (err error)

Delete looks up documents matching the filter via FT.SEARCH, then removes the underlying keys with DEL.

func (*Store) Index

func (s *Store) Index(ctx context.Context, request *vectorstore.IndexRequest) (err error)

Index embeds documents and writes them as Redis HASHes keyed by `<KeyPrefix><id>`.

func (*Store) Search

func (s *Store) Search(ctx context.Context, req *vectorstore.SearchRequest) (response *vectorstore.SearchResponse, err error)

Search embeds the query, runs a KNN search through RediSearch, and returns the matching documents above MinScore.

type StoreConfig

type StoreConfig struct {
	// Client is the go-redis client (single, cluster, or sentinel).
	// Required.
	Client goredis.UniversalClient

	// IndexName names the RediSearch index. Optional: defaults to
	// [DefaultIndexName].
	IndexName string

	// KeyPrefix is the Redis-key prefix the index attaches to —
	// every stored HASH lives at `<KeyPrefix><id>`. Optional:
	// defaults to [DefaultKeyPrefix].
	KeyPrefix string

	// ContentField is the HASH field that holds the original
	// document text. Optional: defaults to [DefaultContentField].
	ContentField string

	// EmbeddingField is the HASH field that holds the binary
	// FLOAT32 vector. Optional: defaults to [DefaultEmbeddingField].
	EmbeddingField string

	// MetadataJSONField is the HASH field that holds the document's metadata
	// as JSON. Optional: defaults to [DefaultMetadataJSONField].
	//
	// It is deliberately absent from the index schema. RediSearch indexes a
	// HASH field's text as its declared type, so a declared field has to hold
	// the value in the form the index expects — which is why the declared
	// fields below cannot also be the metadata of record. A number written to
	// a NUMERIC field reads back as a float64 and everything else as a string,
	// and an undeclared key has no field to read at all, so reconstructing
	// metadata from the index returned a document that differs from the one
	// that was written. This field is the record; the declared fields are the
	// index projection of it.
	MetadataJSONField string

	// MetadataFields enumerates every metadata key the index should
	// understand. Only declared fields can appear in a filter
	// expression — the store rejects unknown identifiers up-front to
	// preclude query injection.
	MetadataFields []MetadataField

	// EmbeddingModel produces vectors for the documents. Required.
	EmbeddingModel embedding.Model

	// DocumentBatcher batches documents before upsert. Required.
	DocumentBatcher vectorstore.Batcher

	// Dimensions sets the vector width registered with a new index, and is
	// required when InitializeSchema is true: the width is part of the vector
	// field definition, and nothing here can read it off an index that does not
	// exist yet.
	Dimensions int

	// DistanceMetric selects the vector similarity function.
	// Optional: defaults to [DistanceCosine].
	DistanceMetric DistanceMetric

	// IndexAlgorithm selects HNSW vs FLAT. Optional: defaults to
	// [AlgorithmHNSW].
	IndexAlgorithm IndexAlgorithm

	// HNSWM / HNSWEFConstruct / HNSWEFRuntime tune the HNSW index.
	// Each defaults via [DefaultHNSW*] when zero. Ignored when
	// IndexAlgorithm is FLAT.
	HNSWM           int
	HNSWEFConstruct int
	HNSWEFRuntime   int

	// InitializeSchema, when true, runs FT.CREATE on construction if
	// the index doesn't already exist. When false, the store assumes
	// the index is pre-provisioned.
	InitializeSchema bool
}

StoreConfig contains configuration options for the Redis vector store.

func (StoreConfig) Validate

func (s StoreConfig) Validate() error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL