Store and search vector records using upsert, query, and the other vector operations. Create a vector index with reserved _values or _sparse_values schema fields; see Serverless Indexes for setup. For full-text search or vectors stored in named document fields, use Working with Documents.
To perform data operations on an index, you target it using the index method. You can target an index by providing its name, or its host.
Best practice: In production, always target indexes by host to avoid the additional network call and potential point of failure from describeIndex(). Get the host from the index response when you create it, or by calling describeIndex() once and caching it:
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
// Get the host from the describe response
const indexModel = await pc.indexes.describe('example-index');
const index = pc.index({ host: indexModel.host });
// Now perform index operations
await index.upsert({
records: [{ id: 'vec1', values: [0.1, 0.2, 0.3, 0.4] }],
});
Or get the host when creating an index:
const indexModel = await pc.indexes.create({
name: 'example-index',
dimension: 1536,
spec: {
serverless: {
cloud: 'aws',
region: 'us-east-1',
},
},
});
// Use the host from the create response
const index = pc.index({ host: indexModel.host });
When you provide only a name, the SDK will automatically call pc.indexes.describe to resolve the index host URL. This is convenient for testing but should be avoided in production:
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const index = pc.index({ name: 'test-index' });
// The SDK calls describeIndex() automatically to get the host
await index.fetch({ ids: ['1'] });
If you are storing metadata alongside your vector values, you can pass a type parameter to index() in order to get proper TypeScript typechecking:
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
type MovieMetadata = {
title: string;
runtime: number;
genre: 'comedy' | 'horror' | 'drama' | 'action';
};
// Specify a custom metadata type while targeting the index
const index = pc.index<MovieMetadata>({ name: 'test-index' });
// Now you get type errors if upserting malformed metadata
await index.upsert({
records: [
{
id: '1234',
values: [0.1, 0.2, 0.3, 0.4], // ... embedding values
metadata: {
title: 'Gone with the Wind',
runtime: 238,
genre: 'drama',
// @ts-expect-error because category property not in MovieMetadata
category: 'classic',
},
},
],
});
The following example returns statistics about the index:
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const indexModel = await pc.indexes.describe('example-index');
const index = pc.index({ host: indexModel.host });
const indexStats = await index.describeIndexStats();
console.log(indexStats);
// {
// namespaces: {
// '': { recordCount: 10 },
// foo: { recordCount: 2000 },
// bar: { recordCount: 2000 }
// },
// dimension: 1536,
// indexFullness: 0,
// totalRecordCount: 4010
// }
Pinecone expects records inserted into indexes to have the following form:
type PineconeRecord = {
id: string;
values: Array<number>;
sparseValues?: Array<number>;
metadata?: object;
};
The following example upserts vectors with metadata:
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const indexModel = await pc.indexes.describe('example-index');
const index = pc.index({ host: indexModel.host });
const upsertResponse = await index.upsert({
records: [
{
id: 'vec1',
values: [0.1, 0.2, 0.3, 0.4],
metadata: { genre: 'drama' },
},
{
id: 'vec2',
values: [0.2, 0.3, 0.4, 0.5],
metadata: { genre: 'action' },
},
],
namespace: 'example-namespace',
});
console.log(upsertResponse);
// { upsertedCount: 2 }
The query method accepts a large number of options. The dimension of the query vector must match the dimension of your index.
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const indexModel = await pc.indexes.describe('my-index');
const index = pc.index({ host: indexModel.host });
const queryResponse = await index.query({
vector: [0.1, 0.2, 0.3, 0.4], // ... query vector
topK: 10,
includeValues: true,
includeMetadata: true,
filter: {
genre: { $in: ['comedy', 'documentary', 'drama'] },
},
namespace: 'example-namespace',
});
console.log(queryResponse);
// {
// matches: [
// {
// id: '556',
// score: 1.00000012,
// values: [0.1, 0.2, 0.3, 0.4],
// sparseValues: undefined,
// metadata: { genre: 'drama' }
// },
// // ... more matches
// ],
// namespace: 'example-namespace',
// usage: { readUnits: 5 }
// }
You can query using the vector values of an existing record in the index by passing a record ID:
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const indexModel = await pc.indexes.describe('my-index');
const index = pc.index({ host: indexModel.host });
const results = await index.query({
id: 'vec1',
topK: 10,
});
The following example fetches vectors by ID:
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const indexModel = await pc.indexes.describe('my-index');
const index = pc.index({ host: indexModel.host });
const fetchResponse = await index.fetch({
ids: ['vec1', 'vec2'],
namespace: 'example-namespace',
});
console.log(fetchResponse);
// {
// records: {
// vec1: {
// id: 'vec1',
// values: [0.1, 0.2, 0.3, 0.4],
// metadata: { genre: 'drama' }
// },
// vec2: {
// id: 'vec2',
// values: [0.2, 0.3, 0.4, 0.5],
// metadata: { genre: 'action' }
// }
// },
// namespace: 'example-namespace'
// }
The following example updates vectors by ID:
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const indexModel = await pc.indexes.describe('my-index');
const index = pc.index({ host: indexModel.host });
await index.update({
id: 'vec1',
values: [0.1, 0.2, 0.3, 0.4],
metadata: { genre: 'drama' },
namespace: 'example-namespace',
});
The following example deletes vectors by ID:
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const indexModel = await pc.indexes.describe('my-index');
const index = pc.index({ host: indexModel.host });
await index.deleteMany({
ids: ['vec1', 'vec2', 'vec3'],
namespace: 'example-namespace',
});
// Or delete a single vector
await index.deleteOne({
id: 'vec1',
namespace: 'example-namespace',
});
Note: Deletion by metadata filter only applies to pod-based indexes.
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const index = pc.index({ name: 'albums-database' });
await index.deleteMany({
filter: { genre: 'rock' },
});
To delete all vectors in a namespace, use the deleteAll method:
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const indexModel = await pc.indexes.describe('my-index');
const index = pc.index({ host: indexModel.host, namespace: 'foo-namespace' });
await index.deleteAll();
If you do not specify a namespace, the records in the default namespace '__default__' will be deleted.
The listPaginated method can be used to list record IDs matching a particular ID prefix in a paginated format. With clever assignment of record ids, this can be used to help model hierarchical relationships between different records such as when there are embeddings for multiple chunks or fragments related to the same document.
import { Pinecone } from '@pinecone-database/pinecone';
const pc = new Pinecone({ apiKey: 'YOUR_API_KEY' });
const indexModel = await pc.indexes.describe('my-index');
const index = pc.index({ host: indexModel.host, namespace: 'my-namespace' });
// Fetch the first 3 vector IDs matching prefix 'doc1#'
const results = await index.listPaginated({
limit: 3,
prefix: 'doc1#',
});
console.log(results);
// {
// vectors: [
// { id: 'doc1#01' },
// { id: 'doc1#02' },
// { id: 'doc1#03' }
// ],
// pagination: {
// next: 'eyJza2lwX3Bhc3QiOiJwcmVUZXN0LS04MCIsInByZWZpeCI6InByZVRlc3QifQ=='
// },
// namespace: 'my-namespace',
// usage: { readUnits: 1 }
// }
// Fetch the next page using the pagination token
const nextResults = await index.listPaginated({
prefix: 'doc1#',
paginationToken: results.pagination?.next,
});
For more information on metadata filtering patterns, see Metadata Filtering.