Skip to main content
Semantic search and lexical search are powerful information retrieval techniques, but each has notable limitations. For example:
  • Semantic search can miss results based on exact keyword matches, especially in scenarios involving domain-specific terminology.
  • Lexical search can miss results based on relationships, such as synonyms and paraphrases.
To work around these limitations, you can use hybrid search, which combines semantic and lexical search.
This page covers the vector-API hybrid pattern: a single index that stores both a dense vector and a sparse vector per record, queried together in one request. For indexes with document schemas, hybrid retrieval is covered in Full-text search, where one schema declares FTS-enabled string (BM25), dense_vector, and sparse_vector fields side by side and you combine signals with text-match filters or by merging results client-side. For multi-signal indexes that combine dense, sparse, and text fields in a single schema, see the Multi-signal index pattern. Both patterns are fully supported; pick by data shape (records vs. JSON documents).
When you query a single index that stores both dense and sparse vectors, BM25 scores and pinecone-sparse-english-v0 sparse-weight outputs are not normalized to the dense vector range (cosine [-1, 1]). Without explicit weighting, the sparse component dominates the combined score. Before going to production, read Normalize sparse and dense values and apply the hybrid_score_norm query-time pattern, or model the workload as an index with a document schema and combine BM25 with a dense or sparse ranking using a text-match filter (or client-side merge) per Full-text search.

Choosing a hybrid pattern

Pinecone supports three hybrid patterns, split by API surface and data shape. Pick the one that matches your data:
PatternAPIData shapeHow signals combineTrade-offs
Single index for dense and sparse vectorsVectorOne record carries both a dense and a sparse vectorServer-side dotproduct of weighted dense + sparse query vectorsSimplest single-request architecture, but BM25/sparse scores are unbounded — requires alpha weighting per query. No integrated embedding.
Separate indexes for dense and sparse vectorsVectorTwo indexes, linked by shared _idTwo queries, merged client-side (e.g., RRF)More moving parts, but supports sparse-only queries, integrated embedding, and independent reranking per index.
Multi-field document schemaDocumentOne document with dense_vector + FTS-enabled string fields in the same schemaEither: dense ranking narrowed by a text-match filter ($match_phrase/$match_all/$match_any); or two searches merged client-sideText-centric workloads; no alpha tuning needed. Doesn’t support integrated embedding in public preview.
Rule of thumb: if your hybrid signal is “I have both vectors per record,” reach for a vector-API pattern (single index or separate indexes). If your hybrid signal is “I have text plus an embedding for the same document,” reach for the document API (multi-field document schema). The remainder of this page covers the vector-API patterns. For the document API hybrid pattern, see Full-text search and the multi-signal schema example.

Hybrid search approaches

There are two ways to perform hybrid search on the vector API: The following table summarizes the key differences between the two approaches:
ApproachProsCons
Single index for both vectors
  • You make requests to only a single index.
  • The linkage between dense and sparse vectors is implicit.
  • Simpler architecture with less operational overhead.
  • You can’t do sparse-only queries.
  • You can’t use integrated embedding and reranking.
Separate indexes per vector type
  • You can start with dense vectors for semantic search and add sparse vectors for lexical search later.
  • You can do sparse-only queries.
  • You can rerank at multiple levels (for each index and for merged results).
  • You can use integrated embedding and reranking.
  • You need to manage and make requests to two separate indexes.
  • You need to maintain the linkage between sparse and dense vectors across indexes.
  • More complex architecture with additional operational overhead.

Choosing the right approach

For most use cases, a single index that stores both dense and sparse vectors is recommended.
  • This approach provides a simpler architecture with less operational overhead. You make requests to a single index rather than managing and querying two separate indexes.
  • The linkage between dense and sparse vectors is implicit, eliminating the need to maintain explicit linkages across indexes.
  • You can perform hybrid queries with a single request, reducing latency and complexity compared to querying separate indexes and merging results.
Consider using separate indexes only when:
  • You need to do sparse-only queries.
  • You want to use Pinecone’s integrated sparse model (pinecone-sparse-english-v0), which only works with indexes that store sparse vectors.
  • You need complete independence in reranking results from each index.
  • You require the flexibility to manage dense and sparse vectors in separate indexes.

Normalize sparse and dense values

A single index that stores both vector types doesn’t reconcile their score ranges. The two scoring components have very different shapes:
  • Dense vectors scored with dotproduct against unit-norm embeddings produce values roughly in [-1, 1] (or close, depending on the embedding model).
  • BM25-style sparse weights and pinecone-sparse-english-v0 outputs are unbounded positive values that scale with term frequency, document length, and vocabulary distribution. Raw scores can run into double digits.
Without explicit weighting, the sparse component dominates the combined score. To make the two signals comparable, apply a convex combination at query time using an alpha parameter:
  • combined = alpha * dense + (1 - alpha) * sparse
  • alpha = 1.0 ranks by dense only (pure semantic).
  • alpha = 0.0 ranks by sparse only (pure lexical).
  • alpha = 0.5 weights the two signals equally.
Pinecone applies this weighting by scaling the query vectors before sending them to the index (the index itself stores raw values). Use the hybrid_score_norm helper documented in the walkthrough below; it multiplies the dense values by alpha and the sparse values by 1 - alpha, so the underlying dotproduct produces the desired combination.

Choosing alpha

There’s no universal best value — alpha depends on your data and query distribution. Reasonable starting points:
  • alpha = 0.75 (dense-leaning) — good default for natural-language queries on conversational or document-style content.
  • alpha = 0.5 — balanced; useful when keyword and semantic signals contribute equally (e.g., mixed exact-match and synonym queries).
  • alpha = 0.25 (sparse-leaning) — good for queries with high keyword specificity (product SKUs, technical IDs, named entities).
We recommend evaluating multiple alpha values against a labeled relevance set drawn from your own workload.
If your workload is text-centric, an index with a document schema sidesteps the alpha-tuning step entirely: declare BM25 and vector fields in one schema and pick a ranking signal per query, with no normalization to fit. See Full-text search.

Use a single index for dense and sparse vectors

To perform hybrid search with a single index that stores both dense and sparse vectors, follow these steps:
1

Create the index

To store both dense and sparse vectors in a single index, use the create_index operation, setting the vector_type to dense and the metric to dotproduct. This is the only combination that supports dense/sparse search on a single index.
Python
2

Generate vectors

Use Pinecone’s hosted embedding models to convert data into dense and sparse vectors.
Python
Python
3

Upsert records with dense and sparse vectors

Use the upsert operation, specifying dense values in the value parameter and sparse values in the sparse_values parameter.
Only indexes that store dense vectors with the dotproduct distance metric accept records that also have sparse vectors. Upserting such records into an index with a different distance metric will succeed, but querying will return an error.
Python
4

Search the index

Use the embed operation to convert your query into a dense vector and a sparse vector, and then use the query operation to search the index for the 40 most relevant records.
Python
Response
5

Search the index with explicit weighting

For a conceptual overview of why this normalization is needed, see Normalize sparse and dense values.Because Pinecone views your sparse-dense vector as a single vector, it does not offer a built-in parameter to adjust the weight of a query’s dense part against its sparse part; the index is agnostic to density or sparsity of coordinates in your vectors. You may, however, incorporate a linear weighting scheme by customizing your query vector, as demonstrated in the function below.The following example transforms vector values using an alpha parameter.
Python
The following example transforms a vector using the above function, then queries a Pinecone index.
Python

Use separate indexes for dense and sparse vectors

To perform hybrid search with separate indexes, follow these steps:
1

Create the indexes

Create one index for dense vectors and another for sparse vectors, either with integrated embedding or for vectors created with external models.For example, the following code creates indexes with integrated embedding models.
Python
2

Upsert dense and sparse vectors

Upsert dense vectors and upsert sparse vectors into their respective indexes.Make sure to establish a linkage between the dense and sparse vectors so you can merge and deduplicate search results later. For example, the following uses _id as the linkage, but you can use any other custom field as well. Because the indexes are integrated with embedding models, you provide the source texts and Pinecone converts them to vectors automatically.
Python
Python
3

Search by dense vectors

Perform a semantic search against the index that stores dense vectors.For example, the following code searches that index for 40 records most semantically related to the query “Q3 2024 us economic data”. Because the index is integrated with an embedding model, you provide the query as text and Pinecone converts the text to a dense vector automatically.
Python
Response
4

Search by sparse vectors

Perform a lexical search against the index that stores sparse vectors.For example, the following code searches that index for 40 records that most exactly match the words in the query. Again, because the index is integrated with an embedding model, you provide the query as text and Pinecone converts the text to a sparse vector automatically.
Python
Response
5

Merge and deduplicate the results

Merge the 40 dense and 40 sparse results and deduplicated them based on the field you used to link sparse and dense vectors.For example, the following code merges and deduplicates the results based on the _id field, resulting in 52 unique results.
Python
Response
6

Rerank the results

Use one of Pinecone’s hosted reranking models to rerank the merged and deduplicated results based on a unified relevance score and then return a smaller set of the most highly relevant results.For example, the following code sends the 52 unique results from the last step to the bge-reranker-v2-m3 reranking model and returns the top 10 most relevant results.
Python
Response