Skip to main content
Compatibility: Only available on Node.js.
Elasticsearch is a distributed, RESTful search engine optimized for speed and relevance on production-scale workloads. It supports vector search using the k-nearest neighbor (kNN) algorithm and also custom models for Natural Language Processing (NLP). You can read more about the support of vector search in Elasticsearch here. This guide provides a quick overview for getting started with Elasticsearch vector stores. For detailed documentation of all ElasticVectorSearch features and configurations head to the API reference.

Overview

Integration details

Installation and setup

Install packages

To use Elasticsearch vector stores, you’ll need to install the @langchain/community integration package. LangChain.js accepts @elastic/elasticsearch as the client for Elasticsearch vectorstore. You’ll need to install it as a peer dependency. This guide will also use OpenAI embeddings, which require you to install the @langchain/openai integration package. You can also use other supported embeddings models if you wish.
npm install @langchain/community @elastic/elasticsearch @langchain/openai @langchain/core

Setup Elasticsearch

There are three ways to get started with Elasticsearch: The quickest way to set up Elasticsearch locally for development and testing is using the start-local script. This script sets up Elasticsearch and Kibana in Docker with a single command.
curl -fsSL https://elastic.co/start-local | sh
This script creates an elastic-start-local folder containing:
  • Configuration files for Elasticsearch and Kibana
  • A .env file with connection details and credentials
After running the script, you can find your credentials in the .env file:
cd elastic-start-local
cat .env
The .env file contains ES_LOCAL_URL and ES_LOCAL_API_KEY that you can use to connect:
const config: ClientOptions = {
  node: process.env.ES_LOCAL_URL ?? "http://localhost:9200",
  auth: {
    apiKey: process.env.ES_LOCAL_API_KEY,
  },
};
To stop and start the services:
# Stop the services
./elastic-start-local/stop.sh

# Start the services
./elastic-start-local/start.sh

# Uninstall completely
./elastic-start-local/uninstall.sh
For more information, see the start-local GitHub repository.

Option 2: Docker (manual setup)

You can use the official Docker image to get started. Run a single-node Elasticsearch instance with security disabled. This is not recommended for production use.
docker run -p 9200:9200 -e "discovery.type=single-node" -e "xpack.security.enabled=false" -e "xpack.security.http.ssl.enabled=false" docker.elastic.co/elasticsearch/elasticsearch:8.17.0

Option 3: Elastic Cloud

Elastic Cloud is a managed Elasticsearch service. You can sign up for a free trial.
  1. Create a deployment
  2. Get your Cloud ID:
    1. In the Elastic Cloud console, click “Manage” next to your deployment
    2. Copy the Cloud ID and paste it into your configuration
  3. Create an API key:
    1. In the Elastic Cloud console, click “Open” next to your deployment
    2. In the left-hand side menu, go to “Stack Management”, then to “API Keys”
    3. Click “Create API key”
    4. Enter a name for the API key and click “Create”
    5. Copy the API key and paste it into your configuration
For connecting to Elastic Cloud you can read the documentation reported here for obtaining an API key.

Credentials

If you are using OpenAI embeddings for this guide, you’ll need to set your OpenAI key:
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"

ElasticVectorSearch

The ElasticVectorSearch class provides Elasticsearch as a vector store with support for both standard vector search and hybrid search.

Instantiation

Instantiating Elasticsearch will vary depending on where your instance is hosted.
import {
  ElasticVectorSearch,
  type ElasticClientArgs,
} from "@langchain/community/vectorstores/elasticsearch";
import { OpenAIEmbeddings } from "@langchain/openai";

import { Client, type ClientOptions } from "@elastic/elasticsearch";

import * as fs from "node:fs";

const embeddings = new OpenAIEmbeddings({
  model: "text-embedding-3-small",
});

const config: ClientOptions = {
  node: process.env.ELASTIC_URL ?? "https://127.0.0.1:9200",
};

if (process.env.ELASTIC_API_KEY) {
  config.auth = {
    apiKey: process.env.ELASTIC_API_KEY,
  };
} else if (process.env.ELASTIC_USERNAME && process.env.ELASTIC_PASSWORD) {
  config.auth = {
    username: process.env.ELASTIC_USERNAME,
    password: process.env.ELASTIC_PASSWORD,
  };
}
// Local Docker deploys require a TLS certificate
if (process.env.ELASTIC_CERT_PATH) {
  config.tls = {
    ca: fs.readFileSync(process.env.ELASTIC_CERT_PATH),
    rejectUnauthorized: false,
  }
}
const clientArgs: ElasticClientArgs = {
  client: new Client(config),
  indexName: process.env.ELASTIC_INDEX ?? "test_vectorstore",
};

const vectorStore = new ElasticVectorSearch(embeddings, clientArgs);

addDocuments

Add documents to the vector store.
import type { Document } from "@langchain/core/documents";

const document1: Document = {
  pageContent: "The powerhouse of the cell is the mitochondria",
  metadata: { source: "https://example.com" }
};

const document2: Document = {
  pageContent: "Buildings are made out of brick",
  metadata: { source: "https://example.com" }
};

const document3: Document = {
  pageContent: "Mitochondria are made out of lipids",
  metadata: { source: "https://example.com" }
};

const document4: Document = {
  pageContent: "The 2024 Olympics are in Paris",
  metadata: { source: "https://example.com" }
}

const documents = [document1, document2, document3, document4];

await vectorStore.addDocuments(documents, { ids: ["1", "2", "3", "4"] });
[ '1', '2', '3', '4' ]

delete

Delete documents from the vector store by ID.
await vectorStore.delete({ ids: ["4"] });

similaritySearch

Perform a similarity search to find documents similar to a query.
const filter = [{
  operator: "match",
  field: "source",
  value: "https://example.com",
}];

const similaritySearchResults = await vectorStore.similaritySearch("biology", 2, filter);

for (const doc of similaritySearchResults) {
  console.log(`* ${doc.pageContent} [${JSON.stringify(doc.metadata, null)}]`);
}
* The powerhouse of the cell is the mitochondria [{"source":"https://example.com"}]
* Mitochondria are made out of lipids [{"source":"https://example.com"}]
The vector store supports Elasticsearch filter syntax operators.

similaritySearchWithScore

Perform a similarity search and return scores.
const similaritySearchWithScoreResults = await vectorStore.similaritySearchWithScore("biology", 2, filter)

for (const [doc, score] of similaritySearchWithScoreResults) {
  console.log(`* [SIM=${score.toFixed(3)}] ${doc.pageContent} [${JSON.stringify(doc.metadata)}]`);
}
* [SIM=0.374] The powerhouse of the cell is the mitochondria [{"source":"https://example.com"}]
* [SIM=0.370] Mitochondria are made out of lipids [{"source":"https://example.com"}]

asRetriever

Transform the vector store into a retriever for use in chains.
const retriever = vectorStore.asRetriever({
  // Optional filter
  filter: filter,
  k: 2,
});
await retriever.invoke("biology");
[
  Document {
    pageContent: 'The powerhouse of the cell is the mitochondria',
    metadata: { source: 'https://example.com' },
    id: undefined
  },
  Document {
    pageContent: 'Mitochondria are made out of lipids',
    metadata: { source: 'https://example.com' },
    id: undefined
  }
]

HybridRetrievalStrategy

Hybrid search requires Elasticsearch 8.9+ for RRF (Reciprocal Rank Fusion) support.
Hybrid search combines kNN vector search with BM25 full-text search using Reciprocal Rank Fusion (RRF) to improve search relevance. This is useful when you want to leverage both semantic similarity and keyword matching.

Configuration options

ParameterTypeDefaultDescription
rankWindowSizenumber100Number of documents to consider for RRF
rankConstantnumber60RRF constant for score normalization
textFieldstring"text"Field to use for BM25 full-text search

Basic usage

To enable hybrid search, pass a HybridRetrievalStrategy to the constructor:
import {
  ElasticVectorSearch,
  HybridRetrievalStrategy,
  type ElasticClientArgs,
} from "@langchain/community/vectorstores/elasticsearch";

const hybridVectorStore = new ElasticVectorSearch(embeddings, {
  client: new Client(config),
  indexName: "test_hybrid_search",
  strategy: new HybridRetrievalStrategy({
    rankWindowSize: 100,  // Number of documents to consider for RRF
    rankConstant: 60,     // RRF constant for score normalization
    textField: "text",    // Field to use for BM25 full-text search
  }),
});
Once configured, hybrid search is automatically used for all similarity searches:
// This now uses hybrid search (vector + BM25 + RRF)
const results = await hybridVectorStore.similaritySearch(
  "how to prevent muscle soreness while running",
  5
);

Complete hybrid search example

import { Client, ClientOptions } from "@elastic/elasticsearch";
import { OpenAIEmbeddings } from "@langchain/openai";
import {
  ElasticClientArgs,
  ElasticVectorSearch,
  HybridRetrievalStrategy,
} from "@langchain/community/vectorstores/elasticsearch";
import { Document } from "@langchain/core/documents";

// Configure Elasticsearch client
const config: ClientOptions = {
  node: process.env.ES_LOCAL_URL ?? "http://127.0.0.1:9200",
};
if (process.env.ES_LOCAL_API_KEY) {
  config.auth = {
    apiKey: process.env.ES_LOCAL_API_KEY,
  };
}

const embeddings = new OpenAIEmbeddings();

// Create vector store with hybrid search strategy
const clientArgs: ElasticClientArgs = {
  client: new Client(config),
  indexName: "test_hybrid_search",
  strategy: new HybridRetrievalStrategy({
    rankWindowSize: 100,
    rankConstant: 60,
    textField: "text",
  }),
};

const vectorStore = new ElasticVectorSearch(embeddings, clientArgs);

// Add documents
await vectorStore.addDocuments([
  new Document({
    pageContent: "Running improves cardiovascular health and endurance",
    metadata: { category: "fitness" },
  }),
  new Document({
    pageContent: "Proper hydration prevents muscle cramps during exercise",
    metadata: { category: "fitness" },
  }),
  new Document({
    pageContent: "Stretching before running reduces injury risk",
    metadata: { category: "fitness" },
  }),
]);

// Search using hybrid (vector + BM25)
const results = await vectorStore.similaritySearch(
  "how to prevent muscle soreness while running",
  3
);

console.log(results);

Usage for retrieval-augmented generation

For guides on how to use this vector store for retrieval-augmented generation (RAG), see the following sections:

API reference

For detailed documentation of all ElasticVectorSearch features and configurations head to the API reference.
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.