!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}return t}()||function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}(),document.documentElement.setAttribute("data-announcement-bar-initially-dismissed",function(){try{return"true"===localStorage.getItem("docusaurus.announcement.dismiss")}catch(t){}return!1}())

[Skip to main content](#__docusaurus_skipToContent_fallback)

You are viewing the **preview** v0.2 docs. View the **stable** v0.1 docs [here](/v0.1/docs/get_started/introduction/). Leave feedback on the v0.2 docs [here](https://github.com/langchain-ai/langchainjs/discussions/5386).

[

![🦜️🔗 Langchain](/v0.2/img/brand/wordmark.png)![🦜️🔗 Langchain](/v0.2/img/brand/wordmark-dark.png)

](/v0.2/)[Integrations](/v0.2/docs/integrations/platforms/)[API Reference](https://v02.api.js.langchain.com)

[More](#)

*   [People](/v0.2/docs/people/)
*   [Community](/v0.2/docs/community)
*   [Tutorials](/v0.2/docs/additional_resources/tutorials)
*   [Contributing](/v0.2/docs/contributing)

[v0.2](#)

*   [v0.2](/v0.2/docs/introduction)
*   [v0.1](https://js.langchain.com/v0.1/docs/get_started/introduction)

[🦜🔗](#)

*   [LangSmith](https://smith.langchain.com)
*   [LangSmith Docs](https://docs.smith.langchain.com)
*   [LangChain Hub](https://smith.langchain.com/hub)
*   [LangServe](https://github.com/langchain-ai/langserve)
*   [Python Docs](https://python.langchain.com/)

[Chat](https://chatjs.langchain.com)[](https://github.com/langchain-ai/langchainjs)

Search

*   [Introduction](/v0.2/docs/introduction)
*   [Tutorials](/v0.2/docs/tutorials/)
    
    *   [Build a Question Answering application over a Graph Database](/v0.2/docs/tutorials/graph)
    *   [Tutorials](/v0.2/docs/tutorials/)
    *   [Build a Simple LLM Application](/v0.2/docs/tutorials/llm_chain)
    *   [Build a Query Analysis System](/v0.2/docs/tutorials/query_analysis)
    *   [Build a Chatbot](/v0.2/docs/tutorials/chatbot)
    *   [Build an Agent](/v0.2/docs/tutorials/agents)
    *   [Build an Extraction Chain](/v0.2/docs/tutorials/extraction)
    *   [Summarize Text](/v0.2/docs/tutorials/summarization)
    *   [Tagging](/v0.2/docs/tutorials/classification)
    *   [Build a Local RAG Application](/v0.2/docs/tutorials/local_rag)
    *   [Conversational RAG](/v0.2/docs/tutorials/qa_chat_history)
    *   [Build a Retrieval Augmented Generation (RAG) App](/v0.2/docs/tutorials/rag)
    *   [Build a Question/Answering system over SQL data](/v0.2/docs/tutorials/sql_qa)
*   [How-to guides](/v0.2/docs/how_to/)
    
    *   [How-to guides](/v0.2/docs/how_to/)
    *   [How to use example selectors](/v0.2/docs/how_to/example_selectors)
    *   [Installation](/v0.2/docs/how_to/installation)
    *   [How to stream responses from an LLM](/v0.2/docs/how_to/streaming_llm)
    *   [How to stream chat model responses](/v0.2/docs/how_to/chat_streaming)
    *   [How to embed text data](/v0.2/docs/how_to/embed_text)
    *   [How to use few shot examples in chat models](/v0.2/docs/how_to/few_shot_examples_chat)
    *   [How to cache model responses](/v0.2/docs/how_to/llm_caching)
    *   [How to cache chat model responses](/v0.2/docs/how_to/chat_model_caching)
    *   [How to create a custom LLM class](/v0.2/docs/how_to/custom_llm)
    *   [How to use few shot examples](/v0.2/docs/how_to/few_shot_examples)
    *   [How to use output parsers to parse an LLM response into structured format](/v0.2/docs/how_to/output_parser_structured)
    *   [How to return structured data from a model](/v0.2/docs/how_to/structured_output)
    *   [How to add ad-hoc tool calling capability to LLMs and Chat Models](/v0.2/docs/how_to/tools_prompting)
    *   [How to create a custom chat model class](/v0.2/docs/how_to/custom_chat)
    *   [How to do per-user retrieval](/v0.2/docs/how_to/qa_per_user)
    *   [How to track token usage](/v0.2/docs/how_to/chat_token_usage_tracking)
    *   [How to track token usage](/v0.2/docs/how_to/llm_token_usage_tracking)
    *   [How to pass through arguments from one step to the next](/v0.2/docs/how_to/passthrough)
    *   [How to compose prompts together](/v0.2/docs/how_to/prompts_composition)
    *   [How to use legacy LangChain Agents (AgentExecutor)](/v0.2/docs/how_to/agent_executor)
    *   [How to add values to a chain's state](/v0.2/docs/how_to/assign)
    *   [How to attach runtime arguments to a Runnable](/v0.2/docs/how_to/binding)
    *   [How to cache embedding results](/v0.2/docs/how_to/caching_embeddings)
    *   [How to split by character](/v0.2/docs/how_to/character_text_splitter)
    *   [How to manage memory](/v0.2/docs/how_to/chatbots_memory)
    *   [How to do retrieval](/v0.2/docs/how_to/chatbots_retrieval)
    *   [How to use tools](/v0.2/docs/how_to/chatbots_tools)
    *   [How to split code](/v0.2/docs/how_to/code_splitter)
    *   [How to do retrieval with contextual compression](/v0.2/docs/how_to/contextual_compression)
    *   [How to write a custom retriever class](/v0.2/docs/how_to/custom_retriever)
    *   [How to create custom Tools](/v0.2/docs/how_to/custom_tools)
    *   [How to debug your LLM apps](/v0.2/docs/how_to/debugging)
    *   [How to load CSV data](/v0.2/docs/how_to/document_loader_csv)
    *   [How to write a custom document loader](/v0.2/docs/how_to/document_loader_custom)
    *   [How to load data from a directory](/v0.2/docs/how_to/document_loader_directory)
    *   [How to load PDF files](/v0.2/docs/how_to/document_loader_pdf)
    *   [How to load JSON data](/v0.2/docs/how_to/document_loaders_json)
    *   [How to select examples by length](/v0.2/docs/how_to/example_selectors_length_based)
    *   [How to select examples by similarity](/v0.2/docs/how_to/example_selectors_similarity)
    *   [How to use reference examples](/v0.2/docs/how_to/extraction_examples)
    *   [How to handle long text](/v0.2/docs/how_to/extraction_long_text)
    *   [How to do extraction without using function calling](/v0.2/docs/how_to/extraction_parse)
    *   [Fallbacks](/v0.2/docs/how_to/fallbacks)
    *   [Few Shot Prompt Templates](/v0.2/docs/how_to/few_shot)
    *   [How to run custom functions](/v0.2/docs/how_to/functions)
    *   [How to construct knowledge graphs](/v0.2/docs/how_to/graph_constructing)
    *   [How to map values to a database](/v0.2/docs/how_to/graph_mapping)
    *   [How to improve results with prompting](/v0.2/docs/how_to/graph_prompting)
    *   [How to add a semantic layer over the database](/v0.2/docs/how_to/graph_semantic)
    *   [How to reindex data to keep your vectorstore in-sync with the underlying data source](/v0.2/docs/how_to/indexing)
    *   [How to get log probabilities](/v0.2/docs/how_to/logprobs)
    *   [How to add message history](/v0.2/docs/how_to/message_history)
    *   [How to generate multiple embeddings per document](/v0.2/docs/how_to/multi_vector)
    *   [How to generate multiple queries to retrieve data for](/v0.2/docs/how_to/multiple_queries)
    *   [How to parse JSON output](/v0.2/docs/how_to/output_parser_json)
    *   [How to retry when output parsing errors occur](/v0.2/docs/how_to/output_parser_retry)
    *   [How to parse XML output](/v0.2/docs/how_to/output_parser_xml)
    *   [How to invoke runnables in parallel](/v0.2/docs/how_to/parallel)
    *   [How to retrieve the whole document for a chunk](/v0.2/docs/how_to/parent_document_retriever)
    *   [How to partially format prompt templates](/v0.2/docs/how_to/prompts_partial)
    *   [How to add chat history to a question-answering chain](/v0.2/docs/how_to/qa_chat_history_how_to)
    *   [How to return citations](/v0.2/docs/how_to/qa_citations)
    *   [How to return sources](/v0.2/docs/how_to/qa_sources)
    *   [How to stream from a question-answering chain](/v0.2/docs/how_to/qa_streaming)
    *   [How to construct filters](/v0.2/docs/how_to/query_constructing_filters)
    *   [How to add examples to the prompt](/v0.2/docs/how_to/query_few_shot)
    *   [How to deal with high cardinality categorical variables](/v0.2/docs/how_to/query_high_cardinality)
    *   [How to handle multiple queries](/v0.2/docs/how_to/query_multiple_queries)
    *   [How to handle multiple retrievers](/v0.2/docs/how_to/query_multiple_retrievers)
    *   [How to handle cases where no queries are generated](/v0.2/docs/how_to/query_no_queries)
    *   [How to recursively split text by characters](/v0.2/docs/how_to/recursive_text_splitter)
    *   [How to reduce retrieval latency](/v0.2/docs/how_to/reduce_retrieval_latency)
    *   [How to route execution within a chain](/v0.2/docs/how_to/routing)
    *   [How to chain runnables](/v0.2/docs/how_to/sequence)
    *   [How to split text by tokens](/v0.2/docs/how_to/split_by_token)
    *   [How to deal with large databases](/v0.2/docs/how_to/sql_large_db)
    *   [How to use prompting to improve results](/v0.2/docs/how_to/sql_prompting)
    *   [How to do query validation](/v0.2/docs/how_to/sql_query_checking)
    *   [How to stream](/v0.2/docs/how_to/streaming)
    *   [How to create a time-weighted retriever](/v0.2/docs/how_to/time_weighted_vectorstore)
    *   [How to use a chat model to call tools](/v0.2/docs/how_to/tool_calling)
    *   [How to call tools with multi-modal data](/v0.2/docs/how_to/tool_calls_multi_modal)
    *   [How to use LangChain tools](/v0.2/docs/how_to/tools_builtin)
    *   [How use a vector store to retrieve data](/v0.2/docs/how_to/vectorstore_retriever)
    *   [How to create and query vector stores](/v0.2/docs/how_to/vectorstores)
*   [Conceptual guide](/v0.2/docs/concepts)
*   Ecosystem
    
    *   [🦜🛠️ LangSmith](/v0.2/docs/langsmith/)
        
    *   [🦜🕸️LangGraph.js](/v0.2/docs/langgraph)
*   Versions
    
    *   [Overview](/v0.2/docs/versions/overview)
    *   [v0.2](/v0.2/docs/versions/v0_2)
    *   [Release Policy](/v0.2/docs/versions/release_policy)
    *   [Packages](/v0.2/docs/versions/packages)
*   [Security](/v0.2/docs/security)

*   [](/v0.2/)
*   [How-to guides](/v0.2/docs/how_to/)
*   How to reindex data to keep your vectorstore in-sync with the underlying data source

On this page

How to reindex data to keep your vectorstore in-sync with the underlying data source
====================================================================================

Prerequisites

This guide assumes familiarity with the following concepts:

*   [Retrieval-augmented generation (RAG)](/v0.2/docs/tutorials/rag/)
*   [Vector stores](/v0.2/docs/concepts/#vectorstores)

Here, we will look at a basic indexing workflow using the LangChain indexing API.

The indexing API lets you load and keep in sync documents from any source into a vector store. Specifically, it helps:

*   Avoid writing duplicated content into the vector store
*   Avoid re-writing unchanged content
*   Avoid re-computing embeddings over unchanged content

All of which should save you time and money, as well as improve your vector search results.

Crucially, the indexing API will work even with documents that have gone through several transformation steps (e.g., via text chunking) with respect to the original source documents.

How it works[​](#how-it-works "Direct link to How it works")
------------------------------------------------------------

LangChain indexing makes use of a record manager (`RecordManager`) that keeps track of document writes into the vector store.

When indexing content, hashes are computed for each document, and the following information is stored in the record manager:

*   the document hash (hash of both page content and metadata)
*   write time
*   the source ID - each document should include information in its metadata to allow us to determine the ultimate source of this document

Deletion Modes[​](#deletion-modes "Direct link to Deletion Modes")
------------------------------------------------------------------

When indexing documents into a vector store, it's possible that some existing documents in the vector store should be deleted. In certain situations you may want to remove any existing documents that are derived from the same sources as the new documents being indexed. In others you may want to delete all existing documents wholesale. The indexing API deletion modes let you pick the behavior you want:

Cleanup Mode

De-Duplicates Content

Parallelizable

Cleans Up Deleted Source Docs

Cleans Up Mutations of Source Docs and/or Derived Docs

Clean Up Timing

None

✅

✅

❌

❌

\-

Incremental

✅

✅

❌

✅

Continuously

Full

✅

❌

✅

✅

At end of indexing

`None` does not do any automatic clean up, allowing the user to manually do clean up of old content.

`incremental` and `full` offer the following automated clean up:

*   If the content of the source document or derived documents has changed, both `incremental` or `full` modes will clean up (delete) previous versions of the content.
*   If the source document has been deleted (meaning it is not included in the documents currently being indexed), the full cleanup mode will delete it from the vector store correctly, but the `incremental` mode will not.

When content is mutated (e.g., the source PDF file was revised) there will be a period of time during indexing when both the new and old versions may be returned to the user. This happens after the new content was written, but before the old version was deleted.

*   `incremental` indexing minimizes this period of time as it is able to do clean up continuously, as it writes.
*   `full` mode does the clean up after all batches have been written.

Requirements[​](#requirements "Direct link to Requirements")
------------------------------------------------------------

1.  Do not use with a store that has been pre-populated with content independently of the indexing API, as the record manager will not know that records have been inserted previously.
2.  Only works with LangChain `vectorstore`'s that support: a). document addition by id (`addDocuments` method with ids argument) b). delete by id (delete method with ids argument)

Compatible Vectorstores: [`PGVector`](/v0.2/docs/integrations/vectorstores/pgvector), [`Chroma`](/v0.2/docs/integrations/vectorstores/chroma), [`CloudflareVectorize`](/v0.2/docs/integrations/vectorstores/cloudflare_vectorize), [`ElasticVectorSearch`](/v0.2/docs/integrations/vectorstores/elasticsearch), [`FAISS`](/v0.2/docs/integrations/vectorstores/faiss), [`MomentoVectorIndex`](/v0.2/docs/integrations/vectorstores/momento_vector_index), [`Pinecone`](/v0.2/docs/integrations/vectorstores/pinecone), [`SupabaseVectorStore`](/v0.2/docs/integrations/vectorstores/supabase), [`VercelPostgresVectorStore`](/v0.2/docs/integrations/vectorstores/vercel_postgres), [`Weaviate`](/v0.2/docs/integrations/vectorstores/weaviate), [`Xata`](/v0.2/docs/integrations/vectorstores/xata)

Caution[​](#caution "Direct link to Caution")
---------------------------------------------

The record manager relies on a time-based mechanism to determine what content can be cleaned up (when using `full` or `incremental` cleanup modes).

If two tasks run back-to-back, and the first task finishes before the clock time changes, then the second task may not be able to clean up content.

This is unlikely to be an issue in actual settings for the following reasons:

1.  The `RecordManager` uses higher resolution timestamps.
2.  The data would need to change between the first and the second tasks runs, which becomes unlikely if the time interval between the tasks is small.
3.  Indexing tasks typically take more than a few ms.

Quickstart[​](#quickstart "Direct link to Quickstart")
------------------------------------------------------

    import { PostgresRecordManager } from "@langchain/community/indexes/postgres";import { index } from "langchain/indexes";import { PGVectorStore } from "@langchain/community/vectorstores/pgvector";import { PoolConfig } from "pg";import { OpenAIEmbeddings } from "@langchain/openai";import { CharacterTextSplitter } from "@langchain/textsplitters";import { BaseDocumentLoader } from "langchain/document_loaders/base";// First, follow set-up instructions at// https://js.langchain.com/docs/modules/indexes/vector_stores/integrations/pgvectorconst config = {  postgresConnectionOptions: {    type: "postgres",    host: "127.0.0.1",    port: 5432,    user: "myuser",    password: "ChangeMe",    database: "api",  } as PoolConfig,  tableName: "testlangchain",  columns: {    idColumnName: "id",    vectorColumnName: "vector",    contentColumnName: "content",    metadataColumnName: "metadata",  },};const vectorStore = await PGVectorStore.initialize(  new OpenAIEmbeddings(),  config);// Create a new record managerconst recordManagerConfig = {  postgresConnectionOptions: {    type: "postgres",    host: "127.0.0.1",    port: 5432,    user: "myuser",    password: "ChangeMe",    database: "api",  } as PoolConfig,  tableName: "upsertion_records",};const recordManager = new PostgresRecordManager(  "test_namespace",  recordManagerConfig);// Create the schema if it doesn't existawait recordManager.createSchema();// Index some documentsconst doc1 = {  pageContent: "kitty",  metadata: { source: "kitty.txt" },};const doc2 = {  pageContent: "doggy",  metadata: { source: "doggy.txt" },};/** * Hacky helper method to clear content. See the `full` mode section to to understand why it works. */async function clear() {  await index({    docsSource: [],    recordManager,    vectorStore,    options: {      cleanup: "full",      sourceIdKey: "source",    },  });}// No cleanupawait clear();// This mode does not do automatic clean up of old versions of content; however, it still takes care of content de-duplication.console.log(  await index({    docsSource: [doc1, doc1, doc1, doc1, doc1, doc1],    recordManager,    vectorStore,    options: {      cleanup: undefined,      sourceIdKey: "source",    },  }));/*    {        numAdded: 1,        numUpdated: 0,        numDeleted: 0,        numSkipped: 0,    }*/await clear();console.log(  await index({    docsSource: [doc1, doc2],    recordManager,    vectorStore,    options: {      cleanup: undefined,      sourceIdKey: "source",    },  }));/*    {        numAdded: 2,        numUpdated: 0,        numDeleted: 0,        numSkipped: 0,    }*/// Second time around all content will be skippedconsole.log(  await index({    docsSource: [doc1, doc2],    recordManager,    vectorStore,    options: {      cleanup: undefined,      sourceIdKey: "source",    },  }));/*    {        numAdded: 0,        numUpdated: 0,        numDeleted: 0,        numSkipped: 2,    }*/// Updated content will be added, but old won't be deletedconst doc1Updated = {  pageContent: "kitty updated",  metadata: { source: "kitty.txt" },};console.log(  await index({    docsSource: [doc1Updated, doc2],    recordManager,    vectorStore,    options: {      cleanup: undefined,      sourceIdKey: "source",    },  }));/*    {        numAdded: 1,        numUpdated: 0,        numDeleted: 0,        numSkipped: 1,    }*//*Resulting records in the database:    [        {            pageContent: "kitty",            metadata: { source: "kitty.txt" },        },        {            pageContent: "doggy",            metadata: { source: "doggy.txt" },        },        {            pageContent: "kitty updated",            metadata: { source: "kitty.txt" },        }    ]*/// Incremental modeawait clear();console.log(  await index({    docsSource: [doc1, doc2],    recordManager,    vectorStore,    options: {      cleanup: "incremental",      sourceIdKey: "source",    },  }));/*    {        numAdded: 2,        numUpdated: 0,        numDeleted: 0,        numSkipped: 0,    }*/// Indexing again should result in both documents getting skipped – also skipping the embedding operation!console.log(  await index({    docsSource: [doc1, doc2],    recordManager,    vectorStore,    options: {      cleanup: "incremental",      sourceIdKey: "source",    },  }));/*    {        numAdded: 0,        numUpdated: 0,        numDeleted: 0,        numSkipped: 2,    }*/// If we provide no documents with incremental indexing mode, nothing will change.console.log(  await index({    docsSource: [],    recordManager,    vectorStore,    options: {      cleanup: "incremental",      sourceIdKey: "source",    },  }));/*    {        numAdded: 0,        numUpdated: 0,        numDeleted: 0,        numSkipped: 0,    }*/// If we mutate a document, the new version will be written and all old versions sharing the same source will be deleted.// This only affects the documents with the same source id!const changedDoc1 = {  pageContent: "kitty updated",  metadata: { source: "kitty.txt" },};console.log(  await index({    docsSource: [changedDoc1],    recordManager,    vectorStore,    options: {      cleanup: "incremental",      sourceIdKey: "source",    },  }));/*    {        numAdded: 1,        numUpdated: 0,        numDeleted: 1,        numSkipped: 0,    }*/// Full modeawait clear();// In full mode the user should pass the full universe of content that should be indexed into the indexing function.// Any documents that are not passed into the indexing function and are present in the vectorStore will be deleted!// This behavior is useful to handle deletions of source documents.const allDocs = [doc1, doc2];console.log(  await index({    docsSource: allDocs,    recordManager,    vectorStore,    options: {      cleanup: "full",      sourceIdKey: "source",    },  }));/*    {        numAdded: 2,        numUpdated: 0,        numDeleted: 0,        numSkipped: 0,    }*/// Say someone deleted the first doc:const doc2Only = [doc2];// Using full mode will clean up the deleted content as well.// This afffects all documents regardless of source id!console.log(  await index({    docsSource: doc2Only,    recordManager,    vectorStore,    options: {      cleanup: "full",      sourceIdKey: "source",    },  }));/*    {        numAdded: 0,        numUpdated: 0,        numDeleted: 1,        numSkipped: 1,    }*/await clear();const newDoc1 = {  pageContent: "kitty kitty kitty kitty kitty",  metadata: { source: "kitty.txt" },};const newDoc2 = {  pageContent: "doggy doggy the doggy",  metadata: { source: "doggy.txt" },};const splitter = new CharacterTextSplitter({  separator: "t",  keepSeparator: true,  chunkSize: 12,  chunkOverlap: 2,});const newDocs = await splitter.splitDocuments([newDoc1, newDoc2]);console.log(newDocs);/*[  {    pageContent: 'kitty kit',    metadata: {source: 'kitty.txt'}  },  {    pageContent: 'tty kitty ki',    metadata: {source: 'kitty.txt'}  },  {    pageContent: 'tty kitty',    metadata: {source: 'kitty.txt'},  },  {    pageContent: 'doggy doggy',    metadata: {source: 'doggy.txt'},  {    pageContent: 'the doggy',    metadata: {source: 'doggy.txt'},  }]*/console.log(  await index({    docsSource: newDocs,    recordManager,    vectorStore,    options: {      cleanup: "incremental",      sourceIdKey: "source",    },  }));/*{    numAdded: 5,    numUpdated: 0,    numDeleted: 0,    numSkipped: 0,}*/const changedDoggyDocs = [  {    pageContent: "woof woof",    metadata: { source: "doggy.txt" },  },  {    pageContent: "woof woof woof",    metadata: { source: "doggy.txt" },  },];console.log(  await index({    docsSource: changedDoggyDocs,    recordManager,    vectorStore,    options: {      cleanup: "incremental",      sourceIdKey: "source",    },  }));/*{    numAdded: 2,    numUpdated: 0,    numDeleted: 2,    numSkipped: 0,}*/// Usage with document loaders// Create a document loaderclass MyCustomDocumentLoader extends BaseDocumentLoader {  load() {    return Promise.resolve([      {        pageContent: "kitty",        metadata: { source: "kitty.txt" },      },      {        pageContent: "doggy",        metadata: { source: "doggy.txt" },      },    ]);  }}await clear();const loader = new MyCustomDocumentLoader();console.log(  await index({    docsSource: loader,    recordManager,    vectorStore,    options: {      cleanup: "incremental",      sourceIdKey: "source",    },  }));/*{    numAdded: 2,    numUpdated: 0,    numDeleted: 0,    numSkipped: 0,}*/// Closing resourcesawait recordManager.end();await vectorStore.end();

#### API Reference:

*   [PostgresRecordManager](https://v02.api.js.langchain.com/classes/langchain_community_indexes_postgres.PostgresRecordManager.html) from `@langchain/community/indexes/postgres`
*   index from `langchain/indexes`
*   [PGVectorStore](https://v02.api.js.langchain.com/classes/langchain_community_vectorstores_pgvector.PGVectorStore.html) from `@langchain/community/vectorstores/pgvector`
*   [OpenAIEmbeddings](https://v02.api.js.langchain.com/classes/langchain_openai.OpenAIEmbeddings.html) from `@langchain/openai`
*   [CharacterTextSplitter](https://v02.api.js.langchain.com/classes/langchain_textsplitters.CharacterTextSplitter.html) from `@langchain/textsplitters`
*   BaseDocumentLoader from `langchain/document_loaders/base`

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

You've now learned how to use indexing in your RAG pipelines.

Next, check out some of the other sections on retrieval.

* * *

#### Was this page helpful?

  

#### You can 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 add a semantic layer over the database

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

Next

How to get log probabilities

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

*   [How it works](#how-it-works)
*   [Deletion Modes](#deletion-modes)
*   [Requirements](#requirements)
*   [Caution](#caution)
*   [Quickstart](#quickstart)
*   [Next steps](#next-steps)

Community

*   [Discord](https://discord.gg/cU2adEyC7w)
*   [Twitter](https://twitter.com/LangChainAI)

GitHub

*   [Python](https://github.com/langchain-ai/langchain)
*   [JS/TS](https://github.com/langchain-ai/langchainjs)

More

*   [Homepage](https://langchain.com)
*   [Blog](https://blog.langchain.dev)

Copyright © 2024 LangChain, Inc.