本页还没有译文
本页 109 段还没译成简体中文,下面显示的是英文原文。RedisVectorStore integration
还没翻译译自英文(docs.langchain.com)本页 109 段都还没译
Tip
Compatibility: Only available on Node.js.
Redis is a fast open source, in-memory data store. Since Redis 8.0, RediSearch - the module that enables vector similarity semantic search - is built-in and no longer requires installing a separate module. For older versions of Redis you might need to install the module separately or use the Redis Stack distribution.
This guide provides a quick overview for getting started with Redis vector stores. The @langchain/redis package provides two implementations: FluentRedisVectorStore (recommended, with advanced filtering) and RedisVectorStore (legacy).
Overview
Integration details
| Class | Package | PY support | Downloads | Version |
|---|---|---|---|---|
FluentRedisVectorStore | @langchain/redis | ❌ | ||
RedisVectorStore | @langchain/redis | ✅ |
Setup
To use Redis vector stores, set up a Redis Stack instance with RediSearch enabled and install @langchain/redis and @langchain/core. Install the redis Node.js client when you pass your own createClient instance to RedisVectorStore.
This guide uses OpenAI embeddings as an example. You can use other supported embeddings models instead.
npm install @langchain/redis @langchain/core redis @langchain/openaiyarn add @langchain/redis @langchain/core redis @langchain/openaipnpm add @langchain/redis @langchain/core redis @langchain/openaiYou can set up a Redis instance locally with Docker by following these instructions.
Credentials
Set the REDIS_URL environment variable:
process.env.REDIS_URL = "your-redis-url";If you are using OpenAI embeddings for this guide, set your OpenAI key as well:
process.env.OPENAI_API_KEY = "YOUR_API_KEY";If you want to get automated tracing of your model calls you can also set your LangSmith API key by uncommenting below:
// process.env.LANGSMITH_TRACING="true"
// process.env.LANGSMITH_API_KEY="your-api-key"Instantiation
import { RedisVectorStore } from "@langchain/redis";
import { OpenAIEmbeddings } from "@langchain/openai";
import { createClient } from "redis";
const embeddings = new OpenAIEmbeddings({
model: "text-embedding-3-small",
});
const client = createClient({
url: process.env.REDIS_URL ?? "redis://localhost:6379",
});
await client.connect();
const vectorStore = new RedisVectorStore(embeddings, {
redisClient: client,
indexName: "langchainjs-testing",
});Manage vector store
Add items to vector store
import type { Document } from "@langchain/core/documents";
const document1: Document = {
pageContent: "The powerhouse of the cell is the mitochondria",
metadata: { type: "example" },
};
const document2: Document = {
pageContent: "Buildings are made out of brick",
metadata: { type: "example" },
};
const document3: Document = {
pageContent: "Mitochondria are made out of lipids",
metadata: { type: "example" },
};
const document4: Document = {
pageContent: "The 2024 Olympics are in Paris",
metadata: { type: "example" },
};
const documents = [document1, document2, document3, document4];
await vectorStore.addDocuments(documents);Top-level document ids are currently not supported, but you can delete documents by providing their IDs directly to the vector store.
Query vector store
Once your vector store has been created and the relevant documents have been added you will most likely wish to query it during the running of your chain or agent.
Query directly
Performing a simple similarity search can be done as follows:
const similaritySearchResults = await vectorStore.similaritySearch(
"biology",
2
);
for (const doc of similaritySearchResults) {
console.log(`* ${doc.pageContent} [${JSON.stringify(doc.metadata, null)}]`);
}If you want to execute a similarity search and receive the corresponding scores you can run:
const similaritySearchWithScoreResults =
await vectorStore.similaritySearchWithScore("biology", 2);
for (const [doc, score] of similaritySearchWithScoreResults) {
console.log(
`* [SIM=${score.toFixed(3)}] ${doc.pageContent} [${JSON.stringify(
doc.metadata
)}]`
);
}* [SIM=0.835] The powerhouse of the cell is the mitochondria [{"type":"example"}]
* [SIM=0.852] Mitochondria are made out of lipids [{"type":"example"}]Query by turning into retriever
You can also transform the vector store into a retriever for easier usage in your chains.
const retriever = vectorStore.asRetriever({
k: 2,
});
await retriever.invoke("biology");[
Document {
pageContent: 'The powerhouse of the cell is the mitochondria',
metadata: { type: 'example' },
id: undefined
},
Document {
pageContent: 'Mitochondria are made out of lipids',
metadata: { type: 'example' },
id: undefined
}
]Usage for retrieval-augmented generation
For guides on how to use this vector store for retrieval-augmented generation (RAG), see the following sections:
Deleting documents
You can delete documents from the vector store in two ways:
Delete all documents
You can delete an entire index and all its documents with the following command:
await vectorStore.delete({ deleteAll: true });Delete specific documents by ID
You can also delete specific documents by providing their IDs. Note that the configured key prefix will be automatically added to the IDs you provide:
// The key prefix will be automatically added to each ID
await vectorStore.delete({ ids: ["doc1", "doc2", "doc3"] });Closing connections
Make sure you close the client connection when you are finished to avoid excessive resource consumption:
await client.disconnect();Advanced features
Advanced pre-filtering with the Redis vector store
The @langchain/redis package provides two vector store implementations:
FluentRedisVectorStore(recommended): New implementation with a type-safe fluent filtering API, array-basedcustomSchema, GEO fields, and timestamp filteringRedisVectorStore(legacy): Original implementation with object-based schema and basic filtering capabilities
Note
Which one should I use?
Use FluentRedisVectorStore for new projects or when you need:
- Advanced filtering with type-safe fluent API (
Tag,Num,Text,Geo,Timestampfilters) - Geographic queries
- Timestamp/date filtering
- Complex filter combinations with AND/OR logic
- Cleaner array-based schema definition
Use RedisVectorStore for:
- Existing projects that need backward compatibility
- Simple use cases without advanced filtering requirements
Using FluentRedisVectorStore
The FluentRedisVectorStore provides a modern, type-safe API for advanced metadata filtering.
Defining a schema with FluentRedisVectorStore:
import { FluentRedisVectorStore } from "@langchain/redis";
import type { RedisVectorStoreConfig } from "@langchain/redis";
import { OpenAIEmbeddings } from "@langchain/openai";
import { createClient } from "redis";
const embeddings = new OpenAIEmbeddings({
model: "text-embedding-3-small",
});
const client = createClient({
url: process.env.REDIS_URL ?? "redis://localhost:6379",
});
await client.connect();
// Define custom schema for metadata fields using array format
const customSchema = [
{ name: "category", type: "tag" },
{ name: "price", type: "numeric", options: { sortable: true } },
{ name: "title", type: "text", options: { weight: 2.0 } },
{ name: "location", type: "geo" },
{ name: "created_at", type: "numeric", options: { sortable: true } },
{ name: "brand", type: "tag" },
{ name: "rating", type: "numeric" },
];
const vectorStore = await FluentRedisVectorStore.fromDocuments(
documents,
embeddings,
{
redisClient: client,
indexName: "products",
customSchema,
}
);Note
customSchema is required; inference is for validation only:
FluentRedisVectorStore requires a customSchema. When you create an index with documents, it also infers a schema from document metadata and logs a warning if that inferred schema differs from your customSchema.
Inference rules used for that comparison:
- Strings in "lon,lat" format (e.g.,
"-122.4194,37.7749") → GEO fields - Numbers or Date objects → NUMERIC fields
- Arrays of any type → TAG fields
- All other types → TEXT fields
Define your schema explicitly so you control field types (for example, TEXT vs TAG for strings) and options such as sortable, weight, or caseSensitive.
Using RedisVectorStore (legacy)
The original RedisVectorStore uses an object-based schema format:
import { RedisVectorStore } from "@langchain/redis";
import { SchemaFieldTypes } from "redis";
// Define custom schema for metadata fields using object format
const customSchema = {
userId: {
type: SchemaFieldTypes.TEXT,
required: true,
SORTABLE: true,
},
category: {
type: SchemaFieldTypes.TAG,
SORTABLE: true,
SEPARATOR: ",",
},
score: {
type: SchemaFieldTypes.NUMERIC,
SORTABLE: true,
},
tags: {
type: SchemaFieldTypes.TAG,
SEPARATOR: ",",
CASESENSITIVE: true,
},
description: {
type: SchemaFieldTypes.TEXT,
NOSTEM: true,
WEIGHT: 2.0,
},
};
const vectorStoreWithSchema = new RedisVectorStore(embeddings, {
redisClient: client,
indexName: "langchainjs-custom-schema",
customSchema,
});Schema field types
FluentRedisVectorStore supports four schema field types:
- TEXT: Full-text searchable fields with optional stemming, weighting, and sorting
- TAG: Categorical fields for exact matching, with support for multiple values and custom separators
- NUMERIC: Numeric fields supporting range queries and sorting. Use this for timestamps (store Unix epoch seconds;
Datevalues are converted automatically) - GEO: Geographic coordinate fields for location-based queries (stored as
[longitude, latitude])
Use the Timestamp() filter helper against numeric timestamp fields.
RedisVectorStore (legacy) supports three field types:
- TEXT: Full-text searchable fields
- TAG: Categorical fields for exact matching
- NUMERIC: Numeric fields supporting range queries
Field configuration options
FluentRedisVectorStore (array-based schema):
name: Field name (required)type: Field type -"text","tag","numeric", or"geo"(required)options: Optional configuration object:sortable: Enable sorting on this field (boolean)separator: For TAG fields, specify the separator for multiple values (string, default: ",")caseSensitive: For TAG fields, enable case-sensitive matching (boolean)noStem: For TEXT fields, disable stemming (boolean)weight: For TEXT fields, specify search weight (number, default: 1.0)
RedisVectorStore (object-based schema):
required: Whether the field must be present in metadata (default: false)SORTABLE: Enable sorting on this field (default: undefined)SEPARATOR: For TAG fields, specify the separator for multiple values (default: ",")CASESENSITIVE: For TAG fields, enable case-sensitive matching (Redis expectstrue, not boolean)NOSTEM: For TEXT fields, disable stemming (Redis expectstrue, not boolean)WEIGHT: For TEXT fields, specify search weight (default: 1.0)
Adding documents with schema validation
When using either the RedisVectorStore or FluentRedisVectorStore, the metadata in your documents is compared against the provided custom schema when adding documents if an index is created.
FluentRedisVectorStore (array-based schema):
If there's a mismatch between the schema you defined and the metadata fields inferred from your documents, a warning message is logged to the console:
"The custom schema does not match the metadata schema inferred from the documents.
This is not necessarily an issue, but could indicate an invalid custom schema."
This validation helps you catch potential issues early, such as:
- Defining a field as
numericwhen your documents contain string values - Defining a field as
geowhen your documents don't use the "lon,lat" string format - Missing fields in your schema that exist in your documents
- Type mismatches between schema definition and actual data
RedisVectorStore (object-based schema):
Only validates when customSchema is defined; if no schema exists, validation is skipped entirely. The validation:
- Throws errors if a field marked as required: true is missing (undefined or null)
- Throws errors if a field type does not match the schema type, e.g., NUMERIC schema fields expect number metadata fields
Tip
Best practices for schema validation:
- Use correct data types: Ensure your document metadata matches your schema field types
- GEO fields: Use string format
"longitude,latitude"(e.g.,"-122.4194,37.7749") - TIMESTAMP fields: Use Date objects or numbers (Unix timestamps)
- Arrays for TAG fields: Arrays are automatically inferred as TAG fields
- Test with sample data: Validate your schema with a few documents before bulk indexing
Advanced filtering with the fluent API
Note
Important: The fluent filtering API (Tag, Num, Text, Geo, Timestamp, Custom) is only available with FluentRedisVectorStore. The legacy RedisVectorStore uses a different filtering approach.
The FluentRedisVectorStore provides a powerful fluent API for building complex metadata filters. This API offers type-safe filter construction with support for various field types and logical operations.
Import filter builders:
import {
FluentRedisVectorStore,
Tag,
Num,
Text,
Geo,
Timestamp,
Custom,
} from "@langchain/redis";Simple tag filtering:
// Filter for electronics category
const electronicsFilter = Tag("category").eq("electronics");
const results = await vectorStore.similaritySearch(
"high quality device",
5,
electronicsFilter
);Numeric range filtering:
// Filter for products between $20-$500
const priceFilter = Num("price").between(20, 500);
const results = await vectorStore.similaritySearch(
"quality product",
5,
priceFilter
);
// Other numeric operations
Num("price").eq(99.99); // Exact match
Num("price").gt(50); // Greater than
Num("price").gte(50); // Greater than or equal
Num("price").lt(100); // Less than
Num("price").lte(100); // Less than or equal
Num("price").between(20, 100); // Between (inclusive)Text search filtering:
// Search for titles containing "programming"
const textFilter = Text("title").wildcard("*programming*");
const results = await vectorStore.similaritySearch(
"learning guide",
5,
textFilter
);
// Other text operations
Text("title").eq("exact title"); // Exact match
Text("description").match("guide"); // Text match
Text("title").wildcard("*JavaScript*"); // Wildcard searchGeographic filtering:
// Find items within 50km of San Francisco
const geoFilter = Geo("location").within(-122.4194, 37.7749, 50, "km");
const results = await vectorStore.similaritySearch(
"local products",
5,
geoFilter
);
// Geo coordinates are stored as [longitude, latitude]
const doc = {
pageContent: "Product description",
metadata: {
location: [-122.4194, 37.7749], // [longitude, latitude]
},
};Timestamp filtering:
// Find items created after March 1, 2023
const timestampFilter = Timestamp("created_at").gt(new Date("2023-03-01"));
const results = await vectorStore.similaritySearch(
"recent items",
5,
timestampFilter
);
// Note: Timestamps are stored as Unix epoch timestamps (numbers)
// Date objects are automatically converted during serialization
// and returned as numbers during deserialization
const createdDate = new Date((doc.metadata.created_at as number) * 1000);Complex combined filtering with AND:
// Electronics under $400 in California
const complexFilter = Tag("category")
.eq("electronics")
.and(Num("price").lt(400))
.and(Geo("location").within(-119.4179, 36.7783, 500, "km"));
const results = await vectorStore.similaritySearch(
"affordable electronics",
5,
complexFilter
);OR filtering:
// Books OR items under $30
const orFilter = Tag("category").eq("books").or(Num("price").lt(30));
const results = await vectorStore.similaritySearch(
"affordable items",
5,
orFilter
);Multiple tag values:
// TechCorp OR ViewTech brands
const multiTagFilter = Tag("brand").eq(["TechCorp", "ViewTech"]);
const results = await vectorStore.similaritySearch(
"branded products",
5,
multiTagFilter
);Negation filtering:
// NOT electronics
const negationFilter = Tag("category").ne("electronics");
const results = await vectorStore.similaritySearch(
"non-electronic items",
5,
negationFilter
);Custom filters with raw RediSearch syntax:
// Use raw RediSearch query syntax for advanced cases
const customFilter = Custom("(@category:{electronics} @price:[0 400])");
const results = await vectorStore.similaritySearch(
"affordable tech",
5,
customFilter
);Complete filtering example with FluentRedisVectorStore
Here's a comprehensive example demonstrating various filtering capabilities with FluentRedisVectorStore:
import { createClient } from "redis";
import { OpenAIEmbeddings } from "@langchain/openai";
import {
FluentRedisVectorStore,
Tag,
Num,
Text,
Geo,
Timestamp,
} from "@langchain/redis";
import { Document } from "@langchain/core/documents";
// Connect to Redis
const client = createClient({
url: process.env.REDIS_URL ?? "redis://localhost:6379",
});
await client.connect();
// Sample documents with rich metadata
const docs = [
new Document({
metadata: {
category: "electronics",
price: 299.99,
title: "Wireless Bluetooth Headphones",
location: [-122.4194, 37.7749], // San Francisco
created_at: new Date("2023-01-15"),
brand: "TechCorp",
rating: 4.5,
},
pageContent:
"High-quality wireless Bluetooth headphones with noise cancellation",
}),
new Document({
metadata: {
category: "books",
price: 24.99,
title: "JavaScript Programming Guide",
location: [-74.006, 40.7128], // New York
created_at: new Date("2023-03-20"),
author: "John Smith",
pages: 450,
},
pageContent:
"Comprehensive guide to modern JavaScript programming techniques",
}),
];
// Create FluentRedisVectorStore with metadata schema
const vectorStore = await FluentRedisVectorStore.fromDocuments(
docs,
new OpenAIEmbeddings(),
{
redisClient: client,
indexName: "advanced_products",
customSchema: [
{ name: "category", type: "tag" },
{ name: "price", type: "numeric", options: { sortable: true } },
{ name: "title", type: "text", options: { weight: 2.0 } },
{ name: "location", type: "geo" },
{ name: "created_at", type: "numeric", options: { sortable: true } },
{ name: "brand", type: "tag" },
{ name: "author", type: "tag" },
{ name: "rating", type: "numeric" },
{ name: "pages", type: "numeric" },
],
}
);
// Example: Complex filtering - Electronics under $400 near San Francisco
const complexFilter = Tag("category")
.eq("electronics")
.and(Num("price").lt(400))
.and(Geo("location").within(-122.4194, 37.7749, 100, "km"));
const results = await vectorStore.similaritySearch(
"affordable electronics",
5,
complexFilter
);
// Cleanup
await vectorStore.delete({ deleteAll: true });
await client.disconnect();
Advanced filtering with the legacy API
The legacy RedisVectorStore provides metadata filtering capabilities using the similaritySearchVectorWithScoreAndMetadata method:
// Search with TAG filtering
const tagFilterResults =
await vectorStoreWithSchema.similaritySearchVectorWithScoreAndMetadata(
await embeddings.embedQuery("programming tutorial"),
3,
{
category: "programming", // Exact tag match
tags: ["javascript", "frontend"], // Multiple tag OR search
}
);
console.log("Tag filter results:");
for (const [doc, score] of tagFilterResults) {
console.log(`* [SIM=${score.toFixed(3)}] ${doc.pageContent}`);
console.log(` Metadata: ${JSON.stringify(doc.metadata)}`);
}// Search with NUMERIC range filtering
const numericFilterResults =
await vectorStoreWithSchema.similaritySearchVectorWithScoreAndMetadata(
await embeddings.embedQuery("high quality content"),
5,
{
score: { min: 90, max: 100 }, // Score between 90 and 100
category: ["programming", "ai"], // Multiple categories
}
);
console.log("Numeric filter results:");
for (const [doc, score] of numericFilterResults) {
console.log(`* [SIM=${score.toFixed(3)}] ${doc.pageContent}`);
console.log(
` Score: ${doc.metadata.score}, Category: ${doc.metadata.category}`
);
}// Search with TEXT field filtering
const textFilterResults =
await vectorStoreWithSchema.similaritySearchVectorWithScoreAndMetadata(
await embeddings.embedQuery("development guide"),
3,
{
description: "comprehensive guide", // Text search in description field
score: { min: 85 }, // Minimum score of 85
}
);
console.log("Text filter results:");
for (const [doc, score] of textFilterResults) {
console.log(`* [SIM=${score.toFixed(3)}] ${doc.pageContent}`);
console.log(` Description: ${doc.metadata.description}`);
}Numeric range query options
For numeric fields, you can specify various range queries:
// Exact value match
{ score: 95 }
// Range with both min and max
{ score: { min: 80, max: 100 } }
// Only minimum value
{ score: { min: 90 } }
// Only maximum value
{ score: { max: 95 } }Performance benefits
Using custom schema and the fluent filtering API provides several performance advantages:
- Indexed Metadata Fields: Individual metadata fields are indexed separately, enabling fast pre-filtering before vector search
- Type-Optimized Queries: Numeric, tag, geo, and text fields use optimized RediSearch query structures
- Reduced Vector Comparisons: Filters are applied before vector similarity calculations, reducing computational overhead
- Better Query Planning: Redis can optimize queries based on field types and indexes
- Type Safety: The fluent API provides compile-time type checking for filter construction
Backward compatibility
Both RedisVectorStore and FluentRedisVectorStore are currently supported and maintained. However, RedisVectorStore is considered legacy and may be deprecated in future major releases. Existing code using RedisVectorStore will continue to work without any changes.
Migration considerations:
- Keep the
customSchemaconfig key, but switch from the object-based format to an array of{ name, type, options }fields - Replace object or string filters with fluent filter expressions (
Tag,Num,Text,Geo,Timestamp,Custom) - GEO schema fields and the
Timestamp()filter helper are only available onFluentRedisVectorStore - Metadata storage differs:
FluentRedisVectorStoreindexes metadata as individual fields and is not compatible with legacy JSON-blob metadata. Create a new index and re-ingest documents rather than pointingFluentRedisVectorStoreat an existing legacy index
API reference
For detailed documentation of all features and configurations: