Adds new vectors to the encrypted index or updates existing vectors if they have the same ID. This operation supports two distinct calling patterns for maximum flexibility.
Method Overloads
Pattern 1: VectorItem Array
async upsert ({
items? : VectorItem [], // Pattern 1: Provide items array
ids? : string [], // Pattern 2: Provide ids and vectors together
vectors? : number [][] // Pattern 2: Provide ids and vectors together
}): Promise < object >
// Note: Must provide either 'items' OR both 'ids' and 'vectors'
Parameters
Pattern 1: VectorItem Array
Parameter Type Description
itemsVectorItem[]Array of vector items to insert or update in the index
Pattern 2: Parallel Arrays
Parameter Type Description
idsstring[]Array of ID strings for each vector vectorsnumber[][]Array of vector embeddings corresponding to each ID
VectorItem Structure
Each VectorItem must contain an id and vector, with optional fields:
Field Type Required Description
idstringYes Unique identifier for the vector item vectornumber[]Yes The vector representation contentsstring | BufferOptional Content associated with the vector (accepts both strings and bytes, encoded to bytes and encrypted before storage) metadataobjectOptional Additional structured data associated with the vector
The contents field accepts both strings and Buffers. All contents are encoded to bytes and encrypted before storage, and will be returned as Buffers when retrieved with get().
Returns
Promise<object>: A Promise that resolves to a response object containing the operation status and message with the count of upserted vectors.
Exceptions
Throws if the API request fails due to network connectivity issues.
Throws if authentication fails (invalid API key).
Throws if the encryption key is invalid for the specified index.
Throws if there are internal server errors preventing the upsert.
Throws detailed validation errors for invalid VectorItem objects.
Throws if vector dimensions don’t match the index configuration.
Throws if required fields are missing from vector items.
Throws if array lengths don’t match in parallel array format.
Throws if vector elements are not finite numbers.
Example Usage
Pattern 1: VectorItem Array (Recommended)
import { Client , VectorItem } from 'cyborgdb' ;
const client = new Client ({ baseUrl: 'http://localhost:8000' , apiKey: 'your-api-key' });
// Load an existing index
const indexKey = new Uint8Array ( Buffer . from ( 'your-stored-hex-key' , 'hex' ));
const index = await client . loadIndex ({ indexName: 'my-vector-index' , indexKey });
// Prepare vector items with rich metadata
const vectorItems : VectorItem [] = [
{
id: 'doc1' ,
vector: [ 0.1 , 0.2 , 0.3 , /* ... additional dimensions */ ],
contents: 'This is the content of the first document' ,
metadata: {
title: 'Introduction to Machine Learning' ,
author: 'Dr. Smith' ,
category: 'education' ,
tags: [ 'ml' , 'ai' , 'tutorial' ],
published_date: '2024-01-15' ,
word_count: 1250
}
},
{
id: 'doc2' ,
vector: [ 0.4 , 0.5 , 0.6 , /* ... additional dimensions */ ],
contents: 'This is the content of the second document' ,
metadata: {
title: 'Advanced Neural Networks' ,
author: 'Dr. Jones' ,
category: 'research' ,
tags: [ 'neural-networks' , 'deep-learning' ],
published_date: '2024-01-20' ,
word_count: 2100
}
}
];
// Upsert vectors
try {
const result = await index . upsert ({ items: vectorItems });
console . log ( 'Upsert result:' , result );
// Typical output: { status: 'success', message: 'Upserted 2 vectors' }
console . log ( `Successfully added ${ vectorItems . length } vectors to the index` );
} catch ( error : any ) {
console . error ( 'Upsert failed:' , error . message );
}
Pattern 2: Parallel Arrays (For Bulk Operations)
// Efficient for bulk operations with just IDs and vectors
const ids = [ 'vec1' , 'vec2' , 'vec3' ];
const vectors = [
[ 0.1 , 0.2 , 0.3 , 0.4 ],
[ 0.5 , 0.6 , 0.7 , 0.8 ],
[ 0.9 , 1.0 , 1.1 , 1.2 ]
];
try {
const result = await index . upsert ({ ids , vectors });
console . log ( 'Bulk upsert result:' , result );
// This approach is more efficient for large datasets
// where you only need IDs and vectors (no metadata/contents)
} catch ( error : any ) {
console . error ( 'Bulk upsert failed:' , error . message );
}
Updating Existing Vectors
// Add initial vector
const initialVector : VectorItem = {
id: 'updatable_doc' ,
vector: [ 0.1 , 0.2 , 0.3 , 0.4 ],
contents: 'Original content' ,
metadata: { version: 1 , status: 'draft' }
};
await index . upsert ({ items: [ initialVector ] });
// Update the same vector with new data
const updatedVector : VectorItem = {
id: 'updatable_doc' , // Same ID - will update existing
vector: [ 0.15 , 0.25 , 0.35 , 0.45 ], // Updated vector
contents: 'Updated content with more information' ,
metadata: {
version: 2 ,
status: 'published' ,
updated_date: '2024-01-25' ,
editor: 'John Doe'
}
};
try {
const updateResult = await index . upsert ({ items: [ updatedVector ] });
console . log ( 'Update result:' , updateResult );
// Verify the update
const retrievedVector = await index . get ({ ids: [ 'updatable_doc' ] });
console . log ( 'Updated vector metadata:' , retrievedVector [ 0 ]. metadata );
} catch ( error : any ) {
console . error ( 'Update failed:' , error . message );
}
Batch Processing with Error Handling
async function processBatchDocuments (
index : EncryptedIndex ,
documents : Array <{
id : string ;
title : string ;
content : string ;
author : string ;
category : string ;
vector : number [];
}>
) : Promise <{ success : boolean ; count : number ; message : string }> {
// Convert documents to VectorItem format
const vectorItems : VectorItem [] = documents . map ( doc => ({
id: doc . id ,
vector: doc . vector ,
contents: doc . content ,
metadata: {
title: doc . title ,
author: doc . author ,
category: doc . category ,
word_count: doc . content . split ( ' ' ). length ,
char_count: doc . content . length ,
processed_date: new Date (). toISOString ()
}
}));
try {
console . log ( `Processing batch of ${ vectorItems . length } documents` );
const result = await index . upsert ({ items: vectorItems });
console . log ( 'Batch upsert completed:' , result );
return {
success: true ,
count: vectorItems . length ,
message: `Successfully processed ${ vectorItems . length } documents`
};
} catch ( error : any ) {
console . error ( 'Batch upsert failed:' , error . message );
// Provide detailed error information
if ( error . message . includes ( 'Invalid VectorItem' )) {
console . error ( 'Validation failed - check your vector data format' );
} else if ( error . message . includes ( 'dimension' )) {
console . error ( 'Vector dimension mismatch - check index configuration' );
}
return {
success: false ,
count: 0 ,
message: `Batch processing failed: ${ error . message } `
};
}
}
// Usage
const documents = [
{
id: 'article_001' ,
title: 'Getting Started with TypeScript' ,
content: 'TypeScript is a powerful superset of JavaScript...' ,
author: 'Jane Developer' ,
category: 'programming' ,
vector: [ 0.1 , 0.2 , 0.3 , 0.4 ]
},
{
id: 'article_002' ,
title: 'React Best Practices' ,
content: 'When building React applications, it is important...' ,
author: 'John React' ,
category: 'frontend' ,
vector: [ 0.5 , 0.6 , 0.7 , 0.8 ]
}
];
const batchResult = await processBatchDocuments ( index , documents );
console . log ( 'Batch processing result:' , batchResult );
// Standard successful upsert response
{
"status" : "success" ,
"message" : "Upserted 5 vectors"
}