Warning: This migration guide is specific to migrating from the v0.x
to v1.x
. Some of the code examples in this guide will no longer work when upgrading to v2.0.0
. Please see the v2-migration guide for details on migrating to the latest version.
This doc will outline the differences between v0.x
beta versions of the Pinecone client and the v1
version. The v1.0.0
release adds a new Pinecone
module export alongside the legacy PineconeClient
export. PineconeClient
is deprecated and will be removed in a future release.
In general, you can expect to see terminology migrate the term vector
to record
in many places to align with our documentation which calls the item stored and retrieved from indexes a "record". Some examples of how this impacts naming in the client:
- Legacy type
Vector
is being replaced withPineconeRecord
- Legacy type
ScoredVector
is being replaced withScoredPineconeRecord
- The
fetch()
method now returnsrecords
instead ofvectors
in the response object. - The
describeIndexStats()
method now returnstotalRecordCount
instead oftotalVectorCount
in the response object.
The old types are still exported from the client, but you're encouraged to adopt the new ones because of their support for generic type params specifying the expected shape of your metadata. For example:
// user-defined metadata type
type MovieMetadata = {
title: string;
genre: 'comedy' | 'drama' | 'horror' | 'action';
};
const records: PineconeRecord<MovieMetadata>[] = [
{
id: '1234',
values: [0.234, 0.143, 0.999], // embedding values, a.k.a. "vector values", simplified
metadata: {
title: 'Ghostbusters',
genre: 'comedy',
},
},
{
id: '1235',
values: [0.675, 0.332, 0.512],
metadata: {
title: 'Vertigo',
genre: 'suspense', // <---- Typescript will flag this type error telling us we made a mistake, yay!
},
},
];
The legacy PineconeClient
export has a two-step async initialization.
// Legacy initialization
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient();
await pineconeClient.init({
apiKey: 'your-api-key',
environment: 'your-environment',
});
The new Pinecone
client constructor accepts the same configuration object and eliminates the async init()
step.
// v1.0.0 initialization
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone({
apiKey: 'your-api-key',
environment: 'your-environment',
});
Also, if you have set values for the environment variables PINECONE_ENVIRONMENT
and PINECONE_API_KEY
then the Pinecone
constructor does not require any additional configuration.
// v1.0.0 initialization
import { Pinecone } from '@pinecone-database/pinecone';
// When no config param, constructor reads from PINECONE_ENVIRONMENT and
// PINECONE_API_KEY environment variables
const pinecone = new Pinecone();
The new Pinecone
client's createIndex
flattens out the method params to remove the top-level createRequest
key. It supports all the same optional configuration parameters.
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient();
await pineconeClient.init({
apiKey: 'your-api-key',
environment: 'your-environment',
});
await pineconeClient.createClient({
createRequest: {
name: 'sample-index',
dimension: 1536,
},
});
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
await pinecone.createIndex({
name: 'sample-index',
dimension: 1536,
});
The new Pinecone
client has flattened out the deleteIndex
method param from an object to a string. Now you only need to pass the name of the index you would like to delete.
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient();
await pineconeClient.init({
apiKey: 'your-api-key',
environment: 'your-environment',
});
await client.deleteIndex({ indexName: 'index-to-delete' });
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
await pinecone.deleteIndex('index-to-delete');
The new Pinecone
client returns an array of objects instead of an array of strings from listIndexes()
. Returning an array of objects creates flexibility for additional data to be returned in the future without creating a breaking change.
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient({
apiKey: 'your-api-key',
environment: 'your-environment',
});
const list = await pineconeClient.listIndexes();
// ['index-name', 'index-name2']
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
const list = await pinecone.listIndexes();
// [{ name: 'index-name' }, { name: 'index-name2' }]
The describeIndex
method of the new Pinecone
client has flattened the required parameters. Now you only need to pass the name of the index you would like to describe.
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient({
apiKey: 'your-api-key',
environment: 'your-environment',
});
const indexDescription = await pineconeClient.describeIndex({
indexName: 'index-name',
});
// {
// database: {
// name: 'index-name',
// dimension: 2,
// indexType: undefined,
// metric: 'cosine',
// pods: 2,
// replicas: 2,
// shards: 1,
// podType: 'p1.x1',
// indexConfig: undefined,
// metadataConfig: { indexed: [ 'description' ] }
// },
// status: { ready: true, state: 'Ready' }
// }
The new client flattens the method params, removes deprecated response field database.indexConfig
and adds new status fields for status.host
and status.port
.
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
await pinecone.describeIndex('test-index');
// {
// database: {
// name: 'test-index',
// dimension: 10,
// metric: 'cosine',
// pods: 1,
// replicas: 1,
// shards: 1,
// podType: 'p1.x1',
// metadataConfig: { indexed: [Array] }
// },
// status: {
// ready: true,
// state: 'Ready',
// host: 'test-index-c01b9b5.svc.us-east1-gcp.pinecone.io',
// port: 433
// }
// }
Both clients support the same configuration variables (replicas
and podType
), but the new Pinecone
client has changed the signature of configureIndex
to separate the name of the target index from the configuration that is going to change. Also, the legacy client returned empty string ''
on completion whereas the new client resolves to undefined.
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient({
apiKey: 'your-api-key',
environment: 'your-environment',
});
await pineconeClient.configureIndex({ indexName: 'my-index', replicas: 2 });
// ''
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
await pinecone.configureIndex('my-index', { replicas: 2 });
New Pinecone
client simplifies these method params.
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient({
apiKey: 'your-api-key',
environment: 'your-environment',
});
await pineconeClient.createCollection({
createCollectionRequest: { source: 'index-name', name: 'collection-name' },
});
// ''
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
await pinecone.createCollection({
source: 'index-name',
name: 'collection-name',
});
The new Pinecone
client simplifies method paramters to describeCollection
and adds new data fields for dimension
and recordCount
in the response.
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient({
apiKey: 'your-api-key',
environment: 'your-environment',
});
await pineconeClient.describeCollection({ collectionName: 'collection3' });
// { name: 'collection3', size: 3126700, status: 'Ready' }
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
await pinecone.describeCollection('collection3')
{
name: 'collection3',
size: 3126700,
status: 'Ready',
dimension: 1536,
recordCount: 99
}
The new Pinecone
client returns an array of objects instead of an array of strings from listCollections
. Returning an array of objects creates flexibility for additional data to be returned in the future without creating a breaking change.
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient({
apiKey: 'your-api-key',
environment: 'your-environment',
});
const list = await pineconeClient.listCollections();
// ['collection-name', 'collection-name2']
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
const list = await pinecone.listCollections();
// [{ name: 'collection-name' }, { name: 'collection-name2' }]
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient({
apiKey: 'your-api-key',
environment: 'your-environment',
});
const index = pineconeClient.Index('movie-embeddings');
In the new Pinecone
client, the index()
method accepts an optional generic type arument that describes the shape of your index's metadata. If you provide this type parameter, the TypeScript compiler will provide appropriate typechecking on your interactions with the index
object when attempting to upsert()
or update()
and you shouldn't need to cast results of query()
and fetch()
operations.
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
type MovieMetadata = {
genre: 'comedy' | 'horror' | 'drama' | 'action' | 'other';
runtime: number;
};
const index = await pinecone.index<MovieMetadata>('movie-embeddings');
The namespace parameter has moved out of the upsert
method param options and been elevated into a chained namespace()
call.
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient({
apiKey: 'your-api-key',
environment: 'your-environment',
});
const index = pineconeClient.Index('movie-embeddings');
await index.upsert({
upsertRequest: {
vectors: [
{
id: '1',
values: [0.1, 0.2, 0.3, 0.4],
metadata: { genre: 'comedy', runtime: 120 },
},
{
id: '2',
values: [0.5, 0.6, 0.7, 0.8],
metadata: { genre: 'horror', runtime: 120 },
},
],
namespace: 'imdb',
},
});
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
type MovieMetadata = {
genre: 'comedy' | 'horror' | 'drama' | 'action' | 'other';
runtime: number;
};
const index = await pinecone.index<MovieMetadata>('movie-embeddings');
const namespace = index.namespace('imdb');
await namespace.upsert([
{
id: '1',
values: [0.1, 0.2, 0.3, 0.4],
metadata: { genre: 'comedy', runtime: 120 },
},
{
id: '2',
values: [0.5, 0.6, 0, 0.8],
metadata: { genre: 'horror', runtime: 120 },
},
]);
In the new Pinecone
client, namespace has been elevated from the fetch()
method param to a chained namespace()
call.
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient({
apiKey: 'your-api-key',
environment: 'your-environment',
});
const index = pineconeClient.Index('movie-embeddings');
const results = await index.fetch({ ids: ['1', '2', '3'], namespace: 'imdb' });
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
type MovieMetadata = {
genre: 'comedy' | 'horror' | 'drama' | 'action' | 'other';
runtime: number;
};
const index = await pinecone.index<MovieMetadata>('movie-embeddings');
const namespace = index.namespace('imdb');
const results = await namespace.fetch(['1', '2', '3']);
In the new Pinecone
client, namespace has been elevated from the query()
method param to a chained namespace()
call. The top-level key queryRequest
has been removed.
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient({
apiKey: 'your-api-key',
environment: 'your-environment',
});
const index = pineconeClient.Index('movie-embeddings');
const results = await index.query({
queryRequest: {
topK: 1,
vector: [...], // actual values here
namespace: 'imdb',
includeMetadata: true,
includeValues: true,
sparseVector: {
indices: [15, 30, 11],
values: [0.1, 0.2, 0.3],
}
}
});
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
type MovieMetadata = {
genre: 'comedy' | 'horror' | 'drama' | 'action' | 'other';
runtime: number;
};
const index = await pinecone.index<MovieMetadata>('movie-embeddings');
const namespace = index.namespace('imdb')
const results = await namespace.query({
topK: 1,
vector: [...], // actual values here
includeMetadata: true,
includeValues: true,
sparseVector: {
indices: [15, 30, 11],
values: [0.1, 0.2, 0.3],
},
});
In the new Pinecone
client, there are convenience methods for deleteOne
, deleteMany
, deleteAll
.
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient({
apiKey: 'your-api-key',
environment: 'your-environment',
});
const index = pineconeClient.Index('movie-embeddings');
// Delete one record by id in namespace
await index.delete1({
ids: ['1'],
namespace: 'imdb',
});
// Delete several record by ids in namespace
await index.delete1({
ids: ['1', '2', '3'],
namespace: 'imdb',
});
// Delete all records in namespace
await index.delete1({
deleteAll: true,
namespace: 'imdb',
});
// Delete all records in namespace with filter
await index.delete1({
deleteAll: true,
namespace: 'imdb',
filter: {
{ $and: [
{ genre: 'comedy' },
{ rating: { $gt: 7.0 } }
]
}
}
});
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
const index = await pinecone.index('movie-embeddings');
const namespace = index.namespace('imdb');
// Delete one record by id in namespace
await namespace.deleteOne('1');
// Delete several record by ids in namespace
await namespace.deleteMany(['1', '2', '3']);
// Delete all records in namesapce with filter expression
await namespace.deleteMany({
$and: [{ genre: 'comedy' }, { rating: { $gt: 7.0 } }],
});
// Delete all records in namespace
await namespace.deleteAll();
// Delete one record by id in default namespace
await index.deleteOne('1');
// Delete several record by ids in default namespace
await index.deleteMany(['1', '2', '3']);
// Delete all records in default namespace
await index.deleteAll();
The return type has changed slightly in the new Pinecone
client. The arguments to describeIndexStats()
have been simplified and the return type has changed totalVectorCount
to totalRecordCount
, vectorCount
to recordCount
.
// v0.x beta releases
import { PineconeClient } from '@pinecone-database/pinecone';
const pineconeClient = new PineconeClient({
apiKey: 'your-api-key',
environment: 'your-environment',
});
const index = pineconeClient.Index('movie-embeddings');
const stats = await index.describeIndexStats({ describeIndexStatsRequest: {} });
// {
// namespaces: { '': { vectorCount: 10001502 } },
// dimension: 256,
// indexFullness: 0.9,
// totalVectorCount: 10001502
// }
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
const index = await pinecone.index('movie-embeddings');
const stats = await index.describeIndexStats();
// {
// namespaces: { '': { recordCount: 10001502 } },
// dimension: 256,
// indexFullness: 0.9,
// totalRecordCount: 10001502
// }
In the v1 client, the needs served by these utility functions in v0.x beta clients are served by additional options to the createIndex
method.
// v0.x beta releases
import { PineconeClient, utils } from '@pinecone-database/pinecone';
const { createIndexIfNotExists, waitUntilIndexIsReady } = utils;
const pineconeClient = new PineconeClient();
await pineconeClient.init({
apiKey: 'your-api-key',
environment: 'your-environment',
});
await createIndexIfNotExists(pineconeClient, 'sample-index', 1536);
await waitUntilIndexIsReady(pineconeClient, 'sample-index');
// v1.0.0
import { Pinecone } from '@pinecone-database/pinecone';
const pinecone = new Pinecone();
await pinecone.createIndex({
name: 'sample-index',
dimension: 1536,
// This option tells the client not to throw if the index already exists.
// It serves as replacement for createIndexIfNotExists
suppressConflicts: true,
// This option tells the client not to resolve the promise until the
// index is ready. It replaces waitUntilIndexIsReady.
waitUntilReady: true,
});