Update data
Patch fields on Pinecone documents by ID, update record metadata and vector values by ID, or update metadata across documents and records with a filter.
This page shows you how to update the data in an index namespace. The kind of index determines which operation you use. An index with a document schema uses the Documents API, and a vector index uses the Vectors API. If you aren't sure which kind of index you have, see Adopt the Documents API.
- Update documents: Patch fields on a document by ID, or patch metadata fields across every document matching a filter.
- Update by ID: Update a single record's metadata (add or change fields) or vector values.
- Update by metadata: Update metadata (add or change fields) across multiple records using a metadata filter. Vector values can't be updated.
To replace whole documents or records, use the upsert operation instead.
Update documents
Section titled “Update documents”In an index with a document schema, upsert replaces the whole document for a given _id. To change individual fields instead, use the documents update operation, which leaves the fields you don't mention unchanged.
To patch specific documents, send one entry per _id. Include the fields you want to set, and name any fields to drop in _remove_fields. Both schema-declared fields and metadata fields can be set or removed this way:
from pinecone import Pinecone
pc = Pinecone(api_key="YOUR_API_KEY")
# To get the unique host for an index,
# see https://docs.pinecone.io/guides/manage-data/target-an-index
index = pc.Index(host="INDEX_HOST")
index.documents.update(
namespace="articles",
documents=[
{"_id": "doc1", "body": "Updated body text."}, # schema-declared field
{"_id": "doc2", "_remove_fields": ["author"]}, # metadata field
],
)PINECONE_API_KEY="YOUR_API_KEY"
INDEX_HOST="INDEX_HOST"
curl "https://$INDEX_HOST/namespaces/articles/documents/update" \
-H "Api-Key: $PINECONE_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Pinecone-Api-Version: 2026-07" \
-d '{
"documents": [
{ "_id": "doc1", "body": "Updated body text." },
{ "_id": "doc2", "_remove_fields": ["author"] }
]
}'To apply the same patch to every document matching a metadata filter expression, send filter with set_fields, remove_fields, or both:
# Connect to an index as shown above.
index.documents.update(
namespace="articles",
filter={"category": {"$eq": "news"}},
set_fields={"status": "archived"},
remove_fields=["author"],
)curl "https://$INDEX_HOST/namespaces/articles/documents/update" \
-H "Api-Key: $PINECONE_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Pinecone-Api-Version: 2026-07" \
-d '{
"filter": { "category": { "$eq": "news" } },
"set_fields": { "status": "archived" },
"remove_fields": ["author"]
}'The response reports how many documents matched the filter:
{
"matched_records": 2
}For the full request and response schema, see Update documents.
Limitations
Section titled “Limitations”- By-ID requests: Each request can patch up to 1,000 documents. See Update limits.
- By-filter requests:
set_fieldsandremove_fieldsboth accept metadata fields only, and reject a field declared in the schema with a400. A by-filter update applies one value to every matched document, which would leave vector and full-text-searchable fields identical across the whole match set. To change a schema-declared field, patch each document by ID.
Update by ID
Section titled “Update by ID”To update the vector and/or metadata of a single record, use the update operation with the following parameters:
namespace: The namespace containing the record to update. To use the default namespace, set the namespace to"__default__".id: The ID of the record to update.- One or both of the following:
- Updated values for the vector. Specify one of the following:
values: For dense vectors. Must have the same length as the existing vector.sparse_values: For sparse vectors.
setMetadata: The metadata to add or change. When updating metadata, only the specified metadata fields are modified, and if a specified metadata field doesn't exist, it's added.
- Updated values for the vector. Specify one of the following:
In this example, assume you are updating the dense vector values and one metadata value of the following record in the example-namespace namespace:
(
namespace="example-namespace",
id="id-3",
values=[4.0, 2.0],
setMetadata={"type": "doc", "genre": "drama"}
)from pinecone.grpc import PineconeGRPC as Pinecone
pc = Pinecone(api_key="YOUR_API_KEY")
# To get the unique host for an index,
# see https://docs.pinecone.io/guides/manage-data/target-an-index
index = pc.Index(host="INDEX_HOST")
index.update(
namespace="example-namespace",
id="id-3",
values=[5.0, 3.0],
set_metadata={"genre": "comedy"}
)import { Pinecone } from '@pinecone-database/pinecone'
const pc = new Pinecone({ apiKey: "YOUR_API_KEY" })
// To get the unique host for an index,
// see https://docs.pinecone.io/guides/manage-data/target-an-index
const index = pc.index("INDEX_NAME", "INDEX_HOST")
await index.namespace('example-namespace').update({
id: 'id-3',
values: [5.0, 3.0],
metadata: {
genre: "comedy",
},
});import com.google.protobuf.Struct;
import com.google.protobuf.Value;
import io.pinecone.clients.Index;
import io.pinecone.configs.PineconeConfig;
import io.pinecone.configs.PineconeConnection;
import io.pinecone.proto.UpdateResponse;
import java.util.Arrays;
import java.util.List;
public class UpdateExample {
public static void main(String[] args) {
PineconeConfig config = new PineconeConfig("YOUR_API_KEY");
// To get the unique host for an index,
// see https://docs.pinecone.io/guides/manage-data/target-an-index
config.setHost("INDEX_HOST");
PineconeConnection connection = new PineconeConnection(config);
Index index = new Index(connection, "INDEX_NAME");
List<Float> values = Arrays.asList(5.0f, 3.0f);
Struct metaData = Struct.newBuilder()
.putFields("genre",
Value.newBuilder().setStringValue("comedy").build())
.build();
UpdateResponse updateResponse = index.update("id-3", values, metaData, "example-namespace", null, null);
System.out.println(updateResponse);
}
}package main
import (
"context"
"log"
"github.com/pinecone-io/go-pinecone/v4/pinecone"
"google.golang.org/protobuf/types/known/structpb"
)
func main() {
ctx := context.Background()
pc, err := pinecone.NewClient(pinecone.NewClientParams{
ApiKey: "YOUR_API_KEY",
})
if err != nil {
log.Fatalf("Failed to create Client: %v", err)
}
// To get the unique host for an index,
// see https://docs.pinecone.io/guides/manage-data/target-an-index
idxConnection, err := pc.Index(pinecone.NewIndexConnParams{Host: "INDEX_HOST", Namespace: "example-namespace"})
if err != nil {
log.Fatalf("Failed to create IndexConnection for Host: %v", err)
}
id := "id-3"
metadataMap := map[string]interface{}{
"genre": "comedy",
}
metadataFilter, err := structpb.NewStruct(metadataMap)
if err != nil {
log.Fatalf("Failed to create metadata map: %v", err)
}
err = idxConnection.UpdateVector(ctx, &pinecone.UpdateVectorRequest{
Id: id,
Values: []float32{5.0, 3.0},
Metadata: metadataFilter,
})
if err != nil {
log.Fatalf("Failed to update vector with ID %v: %v", id, err)
}
}# To get the unique host for an index,
# see https://docs.pinecone.io/guides/manage-data/target-an-index
PINECONE_API_KEY="YOUR_API_KEY"
INDEX_HOST="INDEX_HOST"
# Update both values and metadata
curl "https://$INDEX_HOST/vectors/update" \
-H "Api-Key: $PINECONE_API_KEY" \
-H 'Content-Type: application/json' \
-H "X-Pinecone-Api-Version: 2026-07" \
-d '{
"id": "id-3",
"values": [5.0, 3.0],
"setMetadata": {"genre": "comedy"},
"namespace": "example-namespace"
}'After the update, the dense vector values and the genre metadata value are changed, but the type metadata value is unchanged:
(
id="id-3",
values=[5.0, 3.0],
metadata={"type": "doc", "genre": "comedy"}
)Update by metadata
Section titled “Update by metadata”To add or change metadata across multiple records in a namespace, use the update operation with the following parameters:
-
namespace: The namespace containing the records to update. To use the default namespace, set this to"__default__". -
filter: A metadata filter expression to match the records to update. -
setMetadata: The metadata to add or change. When updating metadata, only the specified metadata fields are modified. If a specified metadata field doesn't exist, it is added. -
dry_run: Optional. Iftrue, the number of records that match the filter expression is returned, but the records aren't updated.
For example, let's say you have records that represent chunks of a single document with metadata that keeps track of chunk and document details, and you want to store the author's name with each chunk of the document:
{
"id": "document1#chunk1",
"values": [0.0236663818359375, -0.032989501953125, ..., -0.01041412353515625, 0.0086669921875],
"metadata": {
"document_id": "document1",
"document_title": "Introduction to Vector Databases",
"chunk_number": 1,
"chunk_text": "First chunk of the document content...",
"document_url": "https://example.com/docs/document1"
}
},
{
"id": "document1#chunk2",
"values": [-0.0412445068359375, 0.028839111328125, ..., 0.01953125, -0.0174560546875],
"metadata": {
"document_id": "document1",
"document_title": "Introduction to Vector Databases",
"chunk_number": 2,
"chunk_text": "Second chunk of the document content...",
"document_url": "https://example.com/docs/document1"
}
},
...The following code updates all matching records with the new author metadata field:
from pinecone.grpc import PineconeGRPC as Pinecone
pc = Pinecone(api_key="YOUR_API_KEY")
# To get the unique host for an index,
# see https://docs.pinecone.io/guides/manage-data/target-an-index
index = pc.Index(host="INDEX_HOST")
# Use dry_run to check how many records match the filter
dry_run_response = index.update(
namespace="example-namespace",
filter={"document_title": {"$eq": "Introduction to Vector Databases"}},
set_metadata={"author": "Del Klein"},
dry_run=True
)
print(dry_run_response.matched_records)
# Perform the update
response = index.update(
namespace="example-namespace",
filter={"document_title": {"$eq": "Introduction to Vector Databases"}},
set_metadata={"author": "Del Klein"}
)import { Pinecone } from '@pinecone-database/pinecone'
const pc = new Pinecone({ apiKey: "YOUR_API_KEY" })
// To get the unique host for an index,
// see https://docs.pinecone.io/guides/manage-data/target-an-index
const index = pc.index("INDEX_NAME", "INDEX_HOST")
await index.namespace('example-namespace').update({
filter: { document_title: { $eq: 'Introduction to Vector Databases' } },
metadata: { author: 'Del Klein' },
});import com.google.protobuf.Struct;
import com.google.protobuf.Value;
import io.pinecone.clients.Index;
import io.pinecone.configs.PineconeConfig;
import io.pinecone.configs.PineconeConnection;
import io.pinecone.proto.UpdateResponse;
public class UpdateByMetadataExample {
public static void main(String[] args) {
PineconeConfig config = new PineconeConfig("YOUR_API_KEY");
// To get the unique host for an index,
// see https://docs.pinecone.io/guides/manage-data/target-an-index
config.setHost("INDEX_HOST");
PineconeConnection connection = new PineconeConnection(config);
Index index = new Index(connection, "INDEX_NAME");
Struct filter = Struct.newBuilder()
.putFields("document_title", Value.newBuilder()
.setStructValue(Struct.newBuilder()
.putFields("$eq", Value.newBuilder()
.setStringValue("Introduction to Vector Databases")
.build())
.build())
.build())
.build();
Struct metadata = Struct.newBuilder()
.putFields("author", Value.newBuilder()
.setStringValue("Del Klein")
.build())
.build();
// Dry run to check how many records match
UpdateResponse dryRunResponse = index.updateByMetadata(
filter, metadata, "example-namespace", true);
System.out.println("Matched records: " + dryRunResponse.getMatchedRecords());
// Perform the update
UpdateResponse response = index.updateByMetadata(
filter, metadata, "example-namespace");
System.out.println(response);
}
}package main
import (
"context"
"fmt"
"log"
"github.com/pinecone-io/go-pinecone/v4/pinecone"
"google.golang.org/protobuf/types/known/structpb"
)
func main() {
ctx := context.Background()
pc, err := pinecone.NewClient(pinecone.NewClientParams{
ApiKey: "YOUR_API_KEY",
})
if err != nil {
log.Fatalf("Failed to create Client: %v", err)
}
// To get the unique host for an index,
// see https://docs.pinecone.io/guides/manage-data/target-an-index
idxConnection, err := pc.Index(pinecone.NewIndexConnParams{
Host: "INDEX_HOST",
Namespace: "example-namespace",
})
if err != nil {
log.Fatalf("Failed to create IndexConnection for Host: %v", err)
}
filter, err := structpb.NewStruct(map[string]interface{}{
"document_title": map[string]interface{}{
"$eq": "Introduction to Vector Databases",
},
})
if err != nil {
log.Fatalf("Failed to create filter: %v", err)
}
metadata, err := structpb.NewStruct(map[string]interface{}{
"author": "Del Klein",
})
if err != nil {
log.Fatalf("Failed to create metadata: %v", err)
}
// Dry run to check how many records match
dryRun := true
dryRunRes, err := idxConnection.UpdateVectorsByMetadata(ctx, &pinecone.UpdateVectorsByMetadataRequest{
Filter: filter,
Metadata: metadata,
DryRun: &dryRun,
})
if err != nil {
log.Fatalf("Failed to dry run update: %v", err)
}
fmt.Printf("Matched records: %d\n", dryRunRes.MatchedRecords)
// Perform the update
res, err := idxConnection.UpdateVectorsByMetadata(ctx, &pinecone.UpdateVectorsByMetadataRequest{
Filter: filter,
Metadata: metadata,
})
if err != nil {
log.Fatalf("Failed to update vectors by metadata: %v", err)
}
fmt.Printf("Updated records: %d\n", res.MatchedRecords)
}# To get the unique host for an index,
# see https://docs.pinecone.io/guides/manage-data/target-an-index
PINECONE_API_KEY="YOUR_API_KEY"
INDEX_HOST="INDEX_HOST"
curl "https://$INDEX_HOST/vectors/update" \
-H "Api-Key: $PINECONE_API_KEY" \
-H 'Content-Type: application/json' \
-H "X-Pinecone-Api-Version: 2026-07" \
-d '{
"namespace": "example-namespace",
"filter": {
"document_title": {"$eq": "Introduction to Vector Databases"}
},
"setMetadata": {
"author": "Del Klein"
}
}'Handling large updates
Section titled “Handling large updates”Each request updates a maximum of 100,000 records. For larger datasets, use dry_run to check the count and repeat the request as needed:
-
To check how many records match the filter expression, send a request with
dry_runset totrue:curl # To get the unique host for an index,# see https://docs.pinecone.io/guides/manage-data/target-an-indexPINECONE_API_KEY="YOUR_API_KEY"INDEX_HOST="INDEX_HOST"curl "https://$INDEX_HOST/vectors/update" \ -H "Api-Key: $PINECONE_API_KEY" \ -H 'Content-Type: application/json' \ -H "X-Pinecone-Api-Version: 2026-07" \ -d '{ "dry_run": true, "namespace": "example-namespace", "filter": { "document_title": {"$eq": "Introduction to Vector Databases"} }, "setMetadata": { "author": "Del Klein" } }'The response contains the number of records that match the filter expression:
JSON { "matchedRecords": 150000 }Since this number exceeds the 100,000 record limit, you'll need to run the update request multiple times.
-
Initiate the first update by sending the request without the
dry_runparameter:curl curl "https://$INDEX_HOST/vectors/update" \ -H "Api-Key: $PINECONE_API_KEY" \ -H 'Content-Type: application/json' \ -H "X-Pinecone-Api-Version: 2026-07" \ -d '{ "namespace": "example-namespace", "filter": { "document_title": {"$eq": "Introduction to Vector Databases"} }, "setMetadata": { "author": "Del Klein" } }'Again, the response contains the total number of records that match the filter expression, but only 100,000 will be updated:
JSON { "matchedRecords": 150000 } -
Pinecone is eventually consistent, so there can be a slight delay before your update request is processed. Repeat the
dry_runrequest until the number of matching records shows that the first 100,000 records have been updated:curl # To get the unique host for an index,# see https://docs.pinecone.io/guides/manage-data/target-an-indexPINECONE_API_KEY="YOUR_API_KEY"INDEX_HOST="INDEX_HOST"curl "https://$INDEX_HOST/vectors/update" \ -H "Api-Key: $PINECONE_API_KEY" \ -H 'Content-Type: application/json' \ -H "X-Pinecone-Api-Version: 2026-07" \ -d '{ "dry_run": true, "namespace": "example-namespace", "filter": { "document_title": {"$eq": "Introduction to Vector Databases"} }, "setMetadata": { "author": "Del Klein" } }'JSON { "matchedRecords": 50000 } -
Once the first 100,000 records have been updated, update the remaining records:
curl curl "https://$INDEX_HOST/vectors/update" \ -H "Api-Key: $PINECONE_API_KEY" \ -H 'Content-Type: application/json' \ -H "X-Pinecone-Api-Version: 2026-07" \ -d '{ "namespace": "example-namespace", "filter": { "document_title": {"$eq": "Introduction to Vector Databases"} }, "setMetadata": { "author": "Del Klein" } }' -
Repeat the
dry_runrequest until the number of matching records shows that the remaining records have been updated:curl # To get the unique host for an index,# see https://docs.pinecone.io/guides/manage-data/target-an-indexPINECONE_API_KEY="YOUR_API_KEY"INDEX_HOST="INDEX_HOST"curl "https://$INDEX_HOST/vectors/update" \ -H "Api-Key: $PINECONE_API_KEY" \ -H 'Content-Type: application/json' \ -H "X-Pinecone-Api-Version: 2026-07" \ -d '{ "dry_run": true, "namespace": "example-namespace", "filter": { "document_title": {"$eq": "Introduction to Vector Databases"} }, "setMetadata": { "author": "Del Klein" } }'JSON { "matchedRecords": 0 }Once the request has completed, all matching records include the author name as metadata:
JSON { "id": "document1#chunk1", "values": [0.0236663818359375, -0.032989501953125, ..., -0.01041412353515625, 0.0086669921875], "metadata": { "document_id": "document1", "document_title": "Introduction to Vector Databases", "chunk_number": 1, "chunk_text": "First chunk of the document content...", "document_url": "https://example.com/docs/document1", "author": "Del Klein" }},{ "id": "document1#chunk2", "values": [-0.0412445068359375, 0.028839111328125, ..., 0.01953125, -0.0174560546875], "metadata": { "document_id": "document1", "document_title": "Introduction to Vector Databases", "chunk_number": 2, "chunk_text": "Second chunk of the document content...", "document_url": "https://example.com/docs/document1", "author": "Del Klein" }},...
Limitations
Section titled “Limitations”- Each request updates a maximum of 100,000 records, per Update limits. Use
"dry_run": trueto check if you need to run the request multiple times. See the example above for details. - Large update-by-metadata requests can be slow to process. A request that matches many records takes longer to complete and to be reflected, so size the work with
dry_runand batch it. See Handling large updates. - You can add or change metadata across multiple records, but you can't remove metadata fields.
Remove a metadata field
Section titled “Remove a metadata field”To remove a metadata field from a record, use the upsert operation to replace the record's metadata, providing the record's existing ID and vector values along with only the metadata you want to keep. Because upsert replaces a record's metadata in full, any fields you omit are cleared.
In an index with a document schema, remove a field with _remove_fields instead of replacing the document. See Update documents.
Data freshness
Section titled “Data freshness”Pinecone is eventually consistent, so there can be a slight delay before updates are visible to queries. You can use log sequence numbers to check whether an update request has completed.