Skip to main content
This page covers how to use Google Vertex AI Vector Search as a vector store in LangChain.

Overview

Google Vertex AI Vector Search is a fully managed, high-scale, low-latency solution for finding similar vectors. It supports both exact and approximate nearest neighbor (ANN) search using Google’s ScaNN (Scalable Nearest Neighbors) technology. Vertex AI Vector Search is available in two versions:
  • Vector Search 2.0: Uses Collections to store Data Objects containing vectors, metadata, and content together. Provides a unified data model with simpler and quicker operations.
  • Vector Search 1.0: Uses Indexes deployed to Endpoints with separate document storage in Google Cloud Storage or Datastore.
Choose the section below based on which version you’re using: For migrating from Vertex AI Vector Search 1.0 to 2.0, see the Migration Guide.

Installation

Install the LangChain Google Vertex AI integration:
pip install -U langchain-google-vertexai

Vector Search 2.0

Vector Search 2.0 uses Collections to store Data Objects. Each Data Object contains vectors, metadata, and content in a unified structure.

Prerequisites

  • Google Cloud project with Vertex AI API and Vector Search APIs enabled
    gcloud services enable vectorsearch.googleapis.com aiplatform.googleapis.com --project "{PROJECT_ID}"
    
  • Vector Search Collection created (see Creating a Collection)
  • Appropriate IAM permissions (Vertex AI User role or equivalent)

Creating a Collection (V2)

Before using Vector Search 2.0, you need to create a collection. Here’s how to create a collection compatible with LangChain:
from google.cloud import vectorsearch_v1beta

# Configuration
PROJECT_ID = "your-project-id"
LOCATION = "us-central1"
COLLECTION_ID = "langchain-test-collection"

# Create the Vector Search service client
vector_search_service_client = vectorsearch_v1beta.VectorSearchServiceClient()

# Create the collection with schema compatible with LangChain
# IMPORTANT: To enable filtering, you must define filterable fields in data_schema.properties
request = vectorsearch_v1beta.CreateCollectionRequest(
    parent=f"projects/{PROJECT_ID}/locations/{LOCATION}",
    collection_id=COLLECTION_ID,
    collection={
        "display_name": "LangChain Test Collection",
        "description": "Collection for testing LangChain VectorSearchVectorStore with filtering",
        "data_schema": {
            "type": "object",
            "properties": {
                # Define fields you want to filter on
                "source": {"type": "string"},
                "category": {"type": "string"},
                "page": {"type": "number"},
                # Add more fields as needed for your specific use case
            },
        },
        "vector_schema": {
            # Vector field must be named "embedding" to match LangChain's default
            "embedding": {
                "dense_vector": {
                    "dimensions": 768  # For text-embedding-005
                }
            },
        },
    },
)

print(f"Creating collection: {COLLECTION_ID}")
operation = vector_search_service_client.create_collection(request=request)
print(f"Operation started: {operation.operation.name}")
print("Waiting for operation to complete...")

result = operation.result()
print(f"Collection created successfully!")
print(f"Resource name: {result.name}")
Important notes:
  • The vector field must be named "embedding" to match LangChain’s default (or use vector_field_name parameter)
  • Only fields defined in data_schema.properties can be used for filtering in V2
  • Dimensions should match your embedding model (768 for text-embedding-005)

Initialization

from langchain_google_vertexai import VectorSearchVectorStore, VertexAIEmbeddings

# Initialize embeddings
embeddings = VertexAIEmbeddings(model_name="text-embedding-005")

# Create vector store from a Collection
# Use the same PROJECT_ID, LOCATION, and COLLECTION_ID from collection creation
vector_store = VectorSearchVectorStore.from_components(
    project_id=PROJECT_ID,
    region=LOCATION,
    collection_id=COLLECTION_ID,
    embedding=embeddings,
    api_version="v2",
)
Key parameters:
  • collection_id: Your Vector Search Collection ID (required)
  • api_version: Must be set to "v2" (required)
  • project_id: GCP project ID (required)
  • region: GCP region where Collection exists (required)
  • vector_field_name: Name of the vector field in your Collection schema (default: "embedding")

Adding Documents

from langchain_core.documents import Document

# Create documents
docs = [
    Document(
        page_content="Google Vertex AI is a managed machine learning platform",
        metadata={"source": "docs", "category": "AI"}
    ),
    Document(
        page_content="LangChain integrates with Vertex AI Vector Search",
        metadata={"source": "blog", "category": "integration"}
    ),
]

# Add documents to vector store
ids = vector_store.add_documents(docs)
print(f"Added documents with IDs: {ids}")

Adding Texts

texts = [
    "Vertex AI provides scalable ML infrastructure",
    "Vector Search enables similarity search at scale",
]

metadatas = [
    {"source": "website", "page": 1},
    {"source": "website", "page": 2},
]

ids = vector_store.add_texts(texts=texts, metadatas=metadatas)

Searching

# Basic similarity search
query = "What is Vertex AI?"
results = vector_store.similarity_search(query, k=5)

for doc in results:
    print(f"Content: {doc.page_content}")
    print(f"Metadata: {doc.metadata}\n")

Similarity Search with Scores

# Get similarity scores along with documents
results_with_scores = vector_store.similarity_search_with_score(
    "What is Vertex AI?",
    k=5
)

for doc, score in results_with_scores:
    print(f"Score: {score}")
    print(f"Content: {doc.page_content}")
    print(f"Metadata: {doc.metadata}\n")

Search by Vector

# Search using a pre-computed embedding
embedding = embeddings.embed_query("Vertex AI features")

results = vector_store.similarity_search_by_vector_with_score(embedding, k=5)

for doc, score in results:
    print(f"Score: {score}")
    print(f"Content: {doc.page_content}\n")

Filtering

Vector Search 2.0 uses dict-based query syntax for filtering Data Objects:
# Simple equality filter
results = vector_store.similarity_search(
    "AI features",
    k=5,
    filter={"source": {"$eq": "docs"}}
)

# Comparison operators
results = vector_store.similarity_search(
    "recent pages",
    k=5,
    filter={"page": {"$gte": 10}}
)

# Logical AND
results = vector_store.similarity_search(
    "AI documentation",
    k=5,
    filter={
        "$and": [
            {"source": {"$eq": "docs"}},
            {"category": {"$eq": "AI"}}
        ]
    }
)

# Logical OR
results = vector_store.similarity_search(
    "documentation",
    k=5,
    filter={
        "$or": [
            {"source": {"$eq": "docs"}},
            {"source": {"$eq": "blog"}}
        ]
    }
)

# Less than
results = vector_store.similarity_search(
    "early pages",
    k=5,
    filter={"page": {"$lt": 5}}
)
Supported operators:
  • $eq: Equals
  • $ne: Not equals
  • $lt: Less than
  • $lte: Less than or equal
  • $gt: Greater than
  • $gte: Greater than or equal
  • $and: Logical AND
  • $or: Logical OR
  • $not: Logical NOT
See the Vector Search 2.0 query documentation for more details.

Delete Operations

Delete by IDs

# Delete specific documents by ID
ids_to_delete = ["id1", "id2", "id3"]
vector_store.delete(ids=ids_to_delete)

Delete by Metadata Filter

Note: Delete by metadata filter has limitations in the current V2 API. The recommended approach is to:
  1. Use similarity_search with your filter to get document IDs
  2. Delete by IDs
# Recommended: Search first, then delete by IDs
results = vector_store.similarity_search(
    "query",  # Use a broad query
    k=1000,   # Get more results
    filter={"source": {"$eq": "old_docs"}}
)
ids_to_delete = [doc.metadata.get("id") for doc in results if "id" in doc.metadata]
vector_store.delete(ids=ids_to_delete)
Alternatively, if direct metadata deletion is supported in your environment:
# Direct deletion by metadata (may have limitations)
try:
    vector_store.delete(metadata={"source": {"$eq": "old_docs"}})
except Exception as e:
    # Fall back to search-then-delete approach
    print(f"Direct deletion failed: {e}")

Advanced Features

Vector Search 2.0 offers several advanced search capabilities that go beyond traditional dense vector search. Semantic search automatically generates embeddings from your query text using Vertex AI models. Your collection must be configured with vertex_embedding_config in the vector schema.
# Semantic search with auto-generated embeddings
results = vector_store.semantic_search(
    query="Tell me about animals",
    k=5,
    search_field="embedding",  # Vector field with auto-embedding config
    task_type="RETRIEVAL_QUERY",  # Optimizes embeddings for search queries
    filter={"category": {"$eq": "wildlife"}}  # Optional filtering
)

for doc in results:
    print(f"Content: {doc.page_content}")
    print(f"Metadata: {doc.metadata}\n")
Task types:
  • RETRIEVAL_QUERY: For search queries (default)
  • RETRIEVAL_DOCUMENT: For document indexing
  • SEMANTIC_SIMILARITY: For semantic similarity tasks
  • CLASSIFICATION: For classification tasks
  • CLUSTERING: For clustering tasks
Text search performs keyword/full-text matching on data fields without using embeddings.
# Keyword search on data fields
results = vector_store.text_search(
    query="Python programming",
    k=10,
    data_field_names=["page_content", "title"]  # Fields to search in
)

for doc in results:
    print(f"Content: {doc.page_content}\n")
!!! note Text search does not support filters. Use semantic_search() or similarity_search() if you need filtering. Hybrid search combines semantic search (with auto-generated embeddings) and text search (keyword matching) using Reciprocal Rank Fusion (RRF) to produce optimally ranked results.
# Hybrid search: semantic understanding + keyword matching
results = vector_store.hybrid_search(
    query="Men's outfit for beach",
    k=10,
    search_field="embedding",  # Vector field with auto-embedding config
    data_field_names=["page_content"],  # Fields for text search
    task_type="RETRIEVAL_QUERY",
    filter={"price": {"$lt": 100}},  # Optional filter for semantic search
    semantic_weight=1.0,  # Weight for semantic results
    text_weight=1.0  # Weight for keyword results
)

for doc in results:
    print(f"Content: {doc.page_content}\n")
Weight parameters:
  • Higher semantic_weight: Prioritizes semantic understanding
  • Higher text_weight: Prioritizes exact keyword matches
  • Equal weights (default): Balanced results
Products appearing high in both semantic and text search results will rank highest in the merged results. See the Vector Search 2.0 documentation for more information.

Custom Vector Field Names

If your Collection schema uses a custom field name for vectors:
vector_store = VectorSearchVectorStore.from_components(
    project_id="your-project-id",
    region="us-central1",
    collection_id="your-collection-id",
    embedding=embeddings,
    api_version="v2",
    vector_field_name="custom_embedding_field",  # Match your schema
)

Additional Resources


Vector Search 1.0

This notebook shows how to use functionality related to the Google Cloud Vertex AI Vector Search vector database.
Google Vertex AI Vector Search, formerly known as Vertex AI Matching Engine, provides the industry’s leading high-scale low latency vector database. These vector databases are commonly referred to as vector similarity-matching or an approximate nearest neighbor (ANN) service.
Note: LangChain API expects an endpoint and deployed index already created.Index creation time can take upto one hour.
To see how to create an index refer to the section Create Index and deploy it to an Endpoint If you already have an index deployed , skip to Create VectorStore from texts

Create index and deploy it to an endpoint

  • This section demonstrates creating a new index and deploying it to an endpoint
# TODO : Set values as per your requirements
# Project and Storage Constants
PROJECT_ID = "<my_project_id>"
REGION = "<my_region>"
BUCKET = "<my_gcs_bucket>"
BUCKET_URI = f"gs://{BUCKET}"

# The number of dimensions for the textembedding-gecko@003 is 768
# If other embedder is used, the dimensions would probably need to change.
DIMENSIONS = 768

# Index Constants
DISPLAY_NAME = "<my_matching_engine_index_id>"
DEPLOYED_INDEX_ID = "<my_matching_engine_endpoint_id>"
# Create a bucket.
! gsutil mb -l $REGION -p $PROJECT_ID $BUCKET_URI

Use VertexAIEmbeddings as the embeddings model

from google.cloud import aiplatform
from langchain_google_vertexai import VertexAIEmbeddings
aiplatform.init(project=PROJECT_ID, location=REGION, staging_bucket=BUCKET_URI)
embedding_model = VertexAIEmbeddings(model_name="text-embedding-005")

Create an empty index

Note : While creating an index you should specify an “index_update_method” from either a “BATCH_UPDATE” or “STREAM_UPDATE”
A batch index is for when you want to update your index in a batch, with data which has been stored over a set amount of time, like systems which are processed weekly or monthly. A streaming index is when you want index data to be updated as new data is added to your datastore, for instance, if you have a bookstore and want to show new inventory online as soon as possible. Which type you choose is important, since setup and requirements are different.
Refer Official Documentation for more details on configuring indexes
# NOTE : This operation can take upto 30 seconds
my_index = aiplatform.MatchingEngineIndex.create_tree_ah_index(
    display_name=DISPLAY_NAME,
    dimensions=DIMENSIONS,
    approximate_neighbors_count=150,
    distance_measure_type="DOT_PRODUCT_DISTANCE",
    index_update_method="STREAM_UPDATE",  # allowed values BATCH_UPDATE , STREAM_UPDATE
)

Create an endpoint

# Create an endpoint
my_index_endpoint = aiplatform.MatchingEngineIndexEndpoint.create(
    display_name=f"{DISPLAY_NAME}-endpoint", public_endpoint_enabled=True
)

Deploy index to the endpoint

# NOTE : This operation can take upto 20 minutes
my_index_endpoint = my_index_endpoint.deploy_index(
    index=my_index, deployed_index_id=DEPLOYED_INDEX_ID
)

my_index_endpoint.deployed_indexes

Create vector store from texts

NOTE : If you have existing Index and Endpoints, you can load them using below code
# TODO : replace 1234567890123456789 with your acutial index ID
my_index = aiplatform.MatchingEngineIndex("1234567890123456789")

# TODO : replace 1234567890123456789 with your acutial endpoint ID
my_index_endpoint = aiplatform.MatchingEngineIndexEndpoint("1234567890123456789")
from langchain_google_vertexai import (
    VectorSearchVectorStore,
    VectorSearchVectorStoreDatastore,
)
Langchainassets.png

Create simple vectorstore ( without filters)

# Input texts
texts = [
    "The cat sat on",
    "the mat.",
    "I like to",
    "eat pizza for",
    "dinner.",
    "The sun sets",
    "in the west.",
]

# Create a Vector Store
vector_store = VectorSearchVectorStore.from_components(
    project_id=PROJECT_ID,
    region=REGION,
    gcs_bucket_name=BUCKET,
    index_id=my_index.name,
    endpoint_id=my_index_endpoint.name,
    embedding=embedding_model,
    stream_update=True,
)

# Add vectors and mapped text chunks to your vectore store
vector_store.add_texts(texts=texts)

OPTIONAL : You can also create vectore and store chunks in a datastore

# NOTE : This operation can take upto 20 mins
vector_store = VectorSearchVectorStoreDatastore.from_components(
    project_id=PROJECT_ID,
    region=REGION,
    index_id=my_index.name,
    endpoint_id=my_index_endpoint.name,
    embedding=embedding_model,
    stream_update=True,
)

vector_store.add_texts(texts=texts, is_complete_overwrite=True)
# Try running a simialarity search
vector_store.similarity_search("pizza")

Create vectorstore with metadata filters

# Input text with metadata
record_data = [
    {
        "description": "A versatile pair of dark-wash denim jeans."
        "Made from durable cotton with a classic straight-leg cut, these jeans"
        " transition easily from casual days to dressier occasions.",
        "price": 65.00,
        "color": "blue",
        "season": ["fall", "winter", "spring"],
    },
    {
        "description": "A lightweight linen button-down shirt in a crisp white."
        " Perfect for keeping cool with breathable fabric and a relaxed fit.",
        "price": 34.99,
        "color": "white",
        "season": ["summer", "spring"],
    },
    {
        "description": "A soft, chunky knit sweater in a vibrant forest green. "
        "The oversized fit and cozy wool blend make this ideal for staying warm "
        "when the temperature drops.",
        "price": 89.99,
        "color": "green",
        "season": ["fall", "winter"],
    },
    {
        "description": "A classic crewneck t-shirt in a soft, heathered blue. "
        "Made from comfortable cotton jersey, this t-shirt is a wardrobe essential "
        "that works for every season.",
        "price": 19.99,
        "color": "blue",
        "season": ["fall", "winter", "summer", "spring"],
    },
    {
        "description": "A flowing midi-skirt in a delicate floral print. "
        "Lightweight and airy, this skirt adds a touch of feminine style "
        "to warmer days.",
        "price": 45.00,
        "color": "white",
        "season": ["spring", "summer"],
    },
]
# Parse and prepare input data

texts = []
metadatas = []
for record in record_data:
    record = record.copy()
    page_content = record.pop("description")
    texts.append(page_content)
    if isinstance(page_content, str):
        metadata = {**record}
        metadatas.append(metadata)
# Inspect metadatas
metadatas
# NOTE : This operation can take more than 20 mins
vector_store = VectorSearchVectorStore.from_components(
    project_id=PROJECT_ID,
    region=REGION,
    gcs_bucket_name=BUCKET,
    index_id=my_index.name,
    endpoint_id=my_index_endpoint.name,
    embedding=embedding_model,
)

vector_store.add_texts(texts=texts, metadatas=metadatas, is_complete_overwrite=True)
from google.cloud.aiplatform.matching_engine.matching_engine_index_endpoint import (
    Namespace,
    NumericNamespace,
)
# Try running a simple similarity search

# Below code should return 5 results
vector_store.similarity_search("shirt", k=5)
# Try running a similarity search with text filter
filters = [Namespace(name="season", allow_tokens=["spring"])]

# Below code should return 4 results now
vector_store.similarity_search("shirt", k=5, filter=filters)
# Try running a similarity search with combination of text and numeric filter
filters = [Namespace(name="season", allow_tokens=["spring"])]
numeric_filters = [NumericNamespace(name="price", value_float=40.0, op="LESS")]

# Below code should return 2 results now
vector_store.similarity_search(
    "shirt", k=5, filter=filters, numeric_filter=numeric_filters
)

Use vector store as retriever

# Initialize the vectore_store as retriever
retriever = vector_store.as_retriever()
# perform simple similarity search on retriever
retriever.invoke("What are my options in breathable fabric?")
# Try running a similarity search with text filter
filters = [Namespace(name="season", allow_tokens=["spring"])]

retriever.search_kwargs = {"filter": filters}

# perform similarity search with filters on retriever
retriever.invoke("What are my options in breathable fabric?")
# Try running a similarity search with combination of text and numeric filter
filters = [Namespace(name="season", allow_tokens=["spring"])]
numeric_filters = [NumericNamespace(name="price", value_float=40.0, op="LESS")]


retriever.search_kwargs = {"filter": filters, "numeric_filter": numeric_filters}

retriever.invoke("What are my options in breathable fabric?")

Use filters with retriever in question answering chains

from langchain_google_vertexai import VertexAI

llm = VertexAI(model_name="gemini-pro")
from langchain_classic.chains import RetrievalQA

filters = [Namespace(name="season", allow_tokens=["spring"])]
numeric_filters = [NumericNamespace(name="price", value_float=40.0, op="LESS")]

retriever.search_kwargs = {"k": 2, "filter": filters, "numeric_filter": numeric_filters}

retrieval_qa = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=retriever,
    return_source_documents=True,
)

question = "What are my options in breathable fabric?"
response = retrieval_qa({"query": question})
print(f"{response['result']}")
print("REFERENCES")
print(f"{response['source_documents']}")

Read , chunk , vectorise and index PDFs

!pip install pypdf
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
loader = PyPDFLoader("https://arxiv.org/pdf/1706.03762.pdf")
pages = loader.load()
text_splitter = RecursiveCharacterTextSplitter(
    # Set a really small chunk size, just to show.
    chunk_size=1000,
    chunk_overlap=20,
    length_function=len,
    is_separator_regex=False,
)
doc_splits = text_splitter.split_documents(pages)
texts = [doc.page_content for doc in doc_splits]
metadatas = [doc.metadata for doc in doc_splits]
texts[0]
# Inspect Metadata of 1st page
metadatas[0]
vector_store = VectorSearchVectorStore.from_components(
    project_id=PROJECT_ID,
    region=REGION,
    gcs_bucket_name=BUCKET,
    index_id=my_index.name,
    endpoint_id=my_index_endpoint.name,
    embedding=embedding_model,
)

vector_store.add_texts(texts=texts, metadatas=metadatas, is_complete_overwrite=True)
vector_store = VectorSearchVectorStore.from_components(
    project_id=PROJECT_ID,
    region=REGION,
    gcs_bucket_name=BUCKET,
    index_id=my_index.name,
    endpoint_id=my_index_endpoint.name,
    embedding=embedding_model,
)

Hybrid search

Vector Search supports hybrid search, a popular architecture pattern in information retrieval (IR) that combines both semantic search and keyword search (also called token-based search). With hybrid search, developers can take advantage of the best of the two approaches, effectively providing higher search quality. Click here to learn more. In order to use hybrid search, we need to fit a sparse embedding vectorizer and handle the embeddings outside of the Vector Search integration. An example of sparse embedding vectorizer is sklearn TfidfVectorizer but other techniques can be used, for instance BM25.
# Define some sample data
texts = [
    "The cat sat on",
    "the mat.",
    "I like to",
    "eat pizza for",
    "dinner.",
    "The sun sets",
    "in the west.",
]

# optional IDs
ids = ["i_" + str(i + 1) for i in range(len(texts))]

# optional metadata
metadatas = [{"my_metadata": i} for i in range(len(texts))]
from sklearn.feature_extraction.text import TfidfVectorizer

# Fit the TFIDF Vectorizer (This is usually done on a very large corpus of data to make sure that word statistics generalize well on new data)
vectorizer = TfidfVectorizer()
vectorizer.fit(texts)
# Utility function to transform text into a TF-IDF Sparse Vector
def get_sparse_embedding(tfidf_vectorizer, text):
    tfidf_vector = tfidf_vectorizer.transform([text])
    values = []
    dims = []
    for i, tfidf_value in enumerate(tfidf_vector.data):
        values.append(float(tfidf_value))
        dims.append(int(tfidf_vector.indices[i]))
    return {"values": values, "dimensions": dims}
# semantic (dense) embeddings
embeddings = embedding_model.embed_documents(texts)
# tfidf (sparse) embeddings
sparse_embeddings = [get_sparse_embedding(vectorizer, x) for x in texts]
sparse_embeddings[0]
# Add the dense and sparse embeddings in Vector Search

vector_store.add_texts_with_embeddings(
    texts=texts,
    embeddings=embeddings,
    sparse_embeddings=sparse_embeddings,
    ids=ids,
    metadatas=metadatas,
)
# Run hybrid search
query = "the cat"
embedding = embedding_model.embed_query(query)
sparse_embedding = get_sparse_embedding(vectorizer, query)

vector_store.similarity_search_by_vector_with_score(
    embedding=embedding,
    sparse_embedding=sparse_embedding,
    k=5,
    rrf_ranking_alpha=0.7,  # 0.7 weight to dense and 0.3 weight to sparse
)

Connect these docs to Claude, VSCode, and more via MCP for real-time answers.