Overview
Pinecone is a managed vector database optimized for similarity search at scale. The LlamaIndex integration provides seamless storage and retrieval of embeddings.
Installation
npm install @llamaindex/pinecone @pinecone-database/pinecone
Basic Usage
import { PineconeVectorStore } from "@llamaindex/pinecone";
import { VectorStoreIndex, Document } from "llamaindex";
const vectorStore = new PineconeVectorStore({
indexName: "my-index",
namespace: "default"
});
const documents = [
new Document({ text: "LlamaIndex is a data framework." }),
new Document({ text: "Pinecone is a vector database." })
];
const index = await VectorStoreIndex.fromDocuments(documents, {
storageContext: { vectorStore }
});
const queryEngine = index.asQueryEngine();
const response = await queryEngine.query({
query: "What is Pinecone?"
});
Constructor Options
Pinecone index name (defaults to PINECONE_INDEX_NAME env var)
Namespace for organizing vectors (defaults to PINECONE_NAMESPACE env var)
Pinecone API key (defaults to PINECONE_API_KEY env var)
Batch size for upsert operations (defaults to PINECONE_CHUNK_SIZE env var)
Metadata key for storing text content
Prerequisites
Create Pinecone Index
- Sign up at Pinecone
- Create an index:
import { Pinecone } from "@pinecone-database/pinecone";
const pc = new Pinecone({ apiKey: process.env.PINECONE_API_KEY });
await pc.createIndex({
name: "my-index",
dimension: 1536, // Match your embedding model
metric: "cosine",
spec: {
serverless: {
cloud: "aws",
region: "us-east-1"
}
}
});
Configuration
Environment Variables
PINECONE_API_KEY=your-api-key
PINECONE_INDEX_NAME=my-index
PINECONE_NAMESPACE=default # Optional
PINECONE_CHUNK_SIZE=100 # Optional
With Custom Client
import { Pinecone } from "@pinecone-database/pinecone";
import { PineconeVectorStore } from "@llamaindex/pinecone";
const pc = new Pinecone({ apiKey: "your-api-key" });
const vectorStore = new PineconeVectorStore({
indexName: "my-index"
});
// The store will create its own client internally
Querying
Basic Query
const index = await VectorStoreIndex.fromVectorStore(vectorStore);
const retriever = index.asRetriever({
similarityTopK: 5
});
const nodes = await retriever.retrieve("query text");
nodes.forEach(node => {
console.log(`Score: ${node.score}`);
console.log(`Text: ${node.node.text}`);
});
import { MetadataFilters } from "@llamaindex/core/vector-store";
const documents = [
new Document({
text: "Doc 1",
metadata: { category: "tech", year: 2023 }
}),
new Document({
text: "Doc 2",
metadata: { category: "science", year: 2024 }
})
];
const index = await VectorStoreIndex.fromDocuments(documents, {
storageContext: { vectorStore }
});
const retriever = index.asRetriever({
filters: new MetadataFilters({
filters: [
{ key: "category", value: "tech" },
{ key: "year", value: 2023, operator: "==" }
]
})
});
const nodes = await retriever.retrieve("query");
Namespaces
Organize vectors into namespaces:
// Store in "production" namespace
const prodStore = new PineconeVectorStore({
indexName: "my-index",
namespace: "production"
});
// Store in "staging" namespace
const stagingStore = new PineconeVectorStore({
indexName: "my-index",
namespace: "staging"
});
Managing Data
Add Documents
const newDoc = new Document({ text: "New content" });
await index.insert(newDoc);
Delete by Document ID
await index.deleteRef(docId);
Clear Index
await vectorStore.clearIndex();
// Note: Not supported on Pinecone Starter (free) tier
Hybrid Search
Combine vector and metadata search:
const retriever = index.asRetriever({
similarityTopK: 10,
filters: new MetadataFilters({
filters: [
{ key: "source", value: "documentation" },
{ key: "date", value: "2024-01-01", operator: ">=" }
]
})
});
Batch Operations
const vectorStore = new PineconeVectorStore({
indexName: "my-index",
chunkSize: 200 // Process 200 vectors at a time
});
const manyDocuments = [...]; // Large document array
const index = await VectorStoreIndex.fromDocuments(manyDocuments, {
storageContext: { vectorStore }
});
// Automatically batches upserts
Loading Existing Index
import { VectorStoreIndex } from "llamaindex";
import { PineconeVectorStore } from "@llamaindex/pinecone";
const vectorStore = new PineconeVectorStore({
indexName: "existing-index"
});
const index = await VectorStoreIndex.fromVectorStore(vectorStore);
const queryEngine = index.asQueryEngine();
Metrics
Pinecone supports different distance metrics:
// When creating index (via Pinecone SDK)
await pc.createIndex({
name: "my-index",
dimension: 1536,
metric: "cosine" // or "euclidean", "dotproduct"
});
Index Stats
const client = await vectorStore.client();
const index = await vectorStore.index();
const stats = await index.describeIndexStats();
console.log("Total vectors:", stats.totalRecordCount);
console.log("Dimensions:", stats.dimension);
Serverless vs Pod-based
Serverless (Recommended)
await pc.createIndex({
name: "serverless-index",
dimension: 1536,
metric: "cosine",
spec: {
serverless: {
cloud: "aws",
region: "us-east-1"
}
}
});
Pod-based
await pc.createIndex({
name: "pod-index",
dimension: 1536,
metric: "cosine",
spec: {
pod: {
environment: "us-east1-gcp",
podType: "p1.x1",
pods: 1
}
}
});
Best Practices
- Match dimensions: Ensure index dimension matches embedding model
- Use namespaces: Organize data by environment or use case
- Batch operations: Use appropriate chunk size for performance
- Monitor costs: Track storage and query usage
- Use metadata filters: Narrow search scope for better results
- Choose right metric: Cosine for normalized vectors, dotproduct for speed
Troubleshooting
Index Not Found
try {
const client = await vectorStore.client();
const indexList = await client.listIndexes();
console.log("Available indexes:", indexList);
} catch (error) {
console.error("Error:", error.message);
}
Dimension Mismatch
Ensure embedding model dimensions match index:
import { OpenAIEmbedding } from "@llamaindex/openai";
// text-embedding-3-small: 1536 dimensions (default)
const embedModel = new OpenAIEmbedding({
model: "text-embedding-3-small"
});
// Pinecone index must also be 1536 dimensions
See Also