*   [](/v0.2/)
*   [How-to guides](/v0.2/docs/how_to/)
*   How to combine results from multiple retrievers

On this page

How to combine results from multiple retrievers
===============================================

Prerequisites

This guide assumes familiarity with the following concepts:

*   [Documents](/v0.2/docs/concepts#document)
*   [Retrievers](/v0.2/docs/concepts#retrievers)

The [EnsembleRetriever](https://api.js.langchain.com/classes/langchain_retrievers_ensemble.EnsembleRetriever.html) supports ensembling of results from multiple retrievers. It is initialized with a list of [BaseRetriever](https://api.js.langchain.com/classes/langchain_core_retrievers.BaseRetriever.html) objects. EnsembleRetrievers rerank the results of the constituent retrievers based on the [Reciprocal Rank Fusion](https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf) algorithm.

By leveraging the strengths of different algorithms, the `EnsembleRetriever` can achieve better performance than any single algorithm.

One useful pattern is to combine a keyword matching retriever with a dense retriever (like embedding similarity), because their strengths are complementary. This can be considered a form of "hybrid search". The sparse retriever is good at finding relevant documents based on keywords, while the dense retriever is good at finding relevant documents based on semantic similarity.

Below we demonstrate ensembling of a [simple custom retriever](/v0.2/docs/how_to/custom_retriever/) that simply returns documents that directly contain the input query with a retriever derived from a [demo, in-memory, vector store](https://api.js.langchain.com/classes/langchain_vectorstores_memory.MemoryVectorStore.html).

    import { EnsembleRetriever } from "langchain/retrievers/ensemble";import { MemoryVectorStore } from "langchain/vectorstores/memory";import { OpenAIEmbeddings } from "@langchain/openai";import { BaseRetriever, BaseRetrieverInput } from "@langchain/core/retrievers";import { Document } from "@langchain/core/documents";class SimpleCustomRetriever extends BaseRetriever {  lc_namespace = [];  documents: Document[];  constructor(fields: { documents: Document[] } & BaseRetrieverInput) {    super(fields);    this.documents = fields.documents;  }  async _getRelevantDocuments(query: string): Promise<Document[]> {    return this.documents.filter((document) =>      document.pageContent.includes(query)    );  }}const docs1 = [  new Document({ pageContent: "I like apples", metadata: { source: 1 } }),  new Document({ pageContent: "I like oranges", metadata: { source: 1 } }),  new Document({    pageContent: "apples and oranges are fruits",    metadata: { source: 1 },  }),];const keywordRetriever = new SimpleCustomRetriever({ documents: docs1 });const docs2 = [  new Document({ pageContent: "You like apples", metadata: { source: 2 } }),  new Document({ pageContent: "You like oranges", metadata: { source: 2 } }),];const vectorstore = await MemoryVectorStore.fromDocuments(  docs2,  new OpenAIEmbeddings());const vectorstoreRetriever = vectorstore.asRetriever();const retriever = new EnsembleRetriever({  retrievers: [vectorstoreRetriever, keywordRetriever],  weights: [0.5, 0.5],});const query = "apples";const retrievedDocs = await retriever.invoke(query);console.log(retrievedDocs);/*  [    Document { pageContent: 'You like apples', metadata: { source: 2 } },    Document { pageContent: 'I like apples', metadata: { source: 1 } },    Document { pageContent: 'You like oranges', metadata: { source: 2 } },    Document {      pageContent: 'apples and oranges are fruits',      metadata: { source: 1 }    }  ]*/

#### API Reference:

*   [EnsembleRetriever](https://v02.api.js.langchain.com/classes/langchain_retrievers_ensemble.EnsembleRetriever.html) from `langchain/retrievers/ensemble`
*   [MemoryVectorStore](https://v02.api.js.langchain.com/classes/langchain_vectorstores_memory.MemoryVectorStore.html) from `langchain/vectorstores/memory`
*   [OpenAIEmbeddings](https://v02.api.js.langchain.com/classes/langchain_openai.OpenAIEmbeddings.html) from `@langchain/openai`
*   [BaseRetriever](https://v02.api.js.langchain.com/classes/langchain_core_retrievers.BaseRetriever.html) from `@langchain/core/retrievers`
*   [BaseRetrieverInput](https://v02.api.js.langchain.com/interfaces/langchain_core_retrievers.BaseRetrieverInput.html) from `@langchain/core/retrievers`
*   [Document](https://v02.api.js.langchain.com/classes/langchain_core_documents.Document.html) from `@langchain/core/documents`

Next steps[​](#next-steps "Direct link to Next steps")
------------------------------------------------------

You've now learned how to combine results from multiple retrievers. Next, check out some other retrieval how-to guides, such as how to [improve results using multiple embeddings per document](/v0.2/docs/how_to/multi_vector) or how to [create your own custom retriever](/v0.2/docs/how_to/custom_retriever).

* * *

#### Was this page helpful?

  

#### You can also leave detailed feedback [on GitHub](https://github.com/langchain-ai/langchainjs/issues/new?assignees=&labels=03+-+Documentation&projects=&template=documentation.yml&title=DOC%3A+%3CPlease+write+a+comprehensive+title+after+the+%27DOC%3A+%27+prefix%3E).

[

Previous

How to load JSON data

](/v0.2/docs/how_to/document_loaders_json)[

Next

How to select examples by length

](/v0.2/docs/how_to/example_selectors_length_based)

*   [Next steps](#next-steps)