AsyncIndex

AsyncIndex is the asynchronous twin of Index: the same data-plane methods, each an async def. Use it inside an async with block. Get one by awaiting pinecone.AsyncPinecone.index(), which resolves the host for you:

from pinecone import AsyncPinecone

pc = AsyncPinecone(api_key="your-api-key")

async with await pc.index("my-index") as idx:
    stats = await idx.describe_index_stats()

Or construct one directly with the index host and an API key, no client needed:

from pinecone import AsyncIndex

async with AsyncIndex(
    host="my-index-abc123.svc.pinecone.io",
    api_key="your-api-key",
) as idx:
    stats = await idx.describe_index_stats()

Leaving the async with block, or calling close(), releases the HTTP connection pool.

Method groups:

class pinecone.async_client.async_index.AsyncIndex(*, host, api_key=None, additional_headers=None, timeout=30.0, proxy_url=None, proxy_headers=None, ssl_ca_certs=None, ssl_verify=True, source_tag=None, connection_pool_maxsize=0, _limiter_registry=None)[source]

Bases: object

Asynchronous data plane client targeting a specific Pinecone index.

An index’s data plane is where its records live, and this is the client that reads and writes them. Reach one with await pc.index(name="article-search"), or construct it here from a host URL when you already know the host and want to skip the describe-index lookup that resolving a name costs. Every method is an async def; Index is the blocking twin.

Only errors specific to a single method are documented on that method. For the exception hierarchy every method shares, see Error handling.

Parameters:
  • host (str) – The index-specific data plane host URL. A scheme you include is kept as given; "http://" is sent in cleartext and emits a RuntimeWarning unless the host is a loopback or RFC 1918 IP address, localhost, or *.localhost.

  • api_key (str | None) – Pinecone API key. Falls back to PINECONE_API_KEY env var.

  • additional_headers (Mapping[str, str] | None) – Extra headers included in every request. A name matching one of the SDK’s own headers, in any capitalization, replaces it.

  • timeout (float) – Request timeout in seconds. Defaults to 30.0.

  • proxy_url (str | None) – HTTP proxy URL for outgoing requests.

  • ssl_ca_certs (str | None) – Path to a CA certificate bundle for SSL verification.

  • ssl_verify (bool) – Whether to verify SSL certificates. Defaults to True.

  • source_tag (str | None) – Tag appended to the User-Agent string for request attribution.

  • connection_pool_maxsize (int) – Maximum number of connections to keep in the pool. 0 (default) uses httpx defaults.

  • proxy_headers (Mapping[str, str] | None)

  • _limiter_registry (_AdaptiveLimiterRegistry | None)

Raises:
  • PineconeValueError – If no API key can be resolved or the host is invalid, or the key is not a valid HTTP header value (blank, or with a trailing newline).

  • FileNotFoundError – If ssl_ca_certs names a path that does not exist, so a mistyped path cannot leave you silently verifying against the default trust store instead. The connection pool is built lazily, so this is raised on the first request rather than at construction. A bundle that exists but cannot be parsed as a certificate raises ssl.SSLError at the same point.

Examples

from pinecone import AsyncPinecone

async with AsyncPinecone(api_key="your-api-key") as pc:
    async with await pc.index(name="article-search") as idx:
        stats = await idx.describe_index_stats()
        print(stats.total_vector_count)

See also

Index — the same surface, blocking. Sync vs async clients — which lane to pick.

__init__(*, host, api_key=None, additional_headers=None, timeout=30.0, proxy_url=None, proxy_headers=None, ssl_ca_certs=None, ssl_verify=True, source_tag=None, connection_pool_maxsize=0, _limiter_registry=None)[source]
Parameters:
  • host (str)

  • api_key (str | None)

  • additional_headers (Mapping[str, str] | None)

  • timeout (float)

  • proxy_url (str | None)

  • proxy_headers (Mapping[str, str] | None)

  • ssl_ca_certs (str | None)

  • ssl_verify (bool)

  • source_tag (str | None)

  • connection_pool_maxsize (int)

  • _limiter_registry (_AdaptiveLimiterRegistry | None)

Return type:

None

property host: str

The data plane host URL for this index.

property documents: AsyncDocuments

Entry point for document operations on a schema-based index.

A schema-based index stores JSON records instead of raw vectors. Reach the document operations — upsert, search, fetch and the rest — through here; the vector methods on this class (upsert(), query()) are for a vector-based index. The same instance is returned on every access, and reaching it does not await.

Returns:

AsyncDocuments namespace instance.

Examples

>>> from pinecone import AsyncIndex
>>> idx = AsyncIndex(host="article-search-abc123.svc.pinecone.io", api_key="...")
>>> idx.documents
AsyncDocuments()

See also

AsyncDocuments — every document operation, with an example each.

async upsert_records(*, records, namespace, timeout=None)[source]

Upsert text records into a legacy integrated index (legacy Records API).

Serves legacy integrated indexes, created with create_for_model(): the server embeds each record’s text with the index’s model. On a document index use documents instead. Upserts apply asynchronously, so a record may not be searchable immediately.

Parameters:
  • records (list[dict[str, Any]]) – Records to write, each with an _id (or id) string plus the fields to store, e.g. {"_id": "article-101", "text": "Vector databases for search."}. The index embeds the field its embed configuration maps and stores the rest with the record. A record giving both _id and id keeps _id.

  • namespace (str) – Target namespace, e.g. "articles-en". Required: the legacy Records API has no implicit default namespace, so pass "__default__" to write to it.

  • timeout (float | None) – Per-request timeout in seconds, e.g. 10.0. Overrides the client-level default for this call only.

Returns:

UpsertRecordsResponse whose record_count is the number of records the client sent.

Raises:

PineconeValueError – If namespace is not a non-empty string, records is empty, or a record has no _id/id field or one that is not a string. Raised before any request is made.

Return type:

UpsertRecordsResponse

Examples

response = await idx.upsert_records(
    namespace="articles-en",
    records=[
        {"_id": "article-101", "text": "Vector databases for search."},
        {"_id": "article-102", "text": "RAG combines search with LLMs."},
    ],
)
print(response.record_count)

See also

  • search(): the read side of a legacy integrated index.

  • upsert(): write vectors you embedded yourself.

async upsert(*, vectors, namespace='', batch_size=None, show_progress=True, max_concurrency=8, timeout=None, total_timeout=None)[source]

Upsert a batch of vectors into a namespace.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use documents instead. A vector whose ID already exists in the namespace is overwritten. Each request is capped on both vector count and encoded size, and wide vectors or large metadata usually hit the size cap first, so pass batch_size to split a long sequence into requests that stay under both.

Parameters:
  • vectors (Sequence[Vector | tuple[str, Sequence[float]] | tuple[str, Sequence[float], Mapping[str, Any]] | Mapping[str, Any]]) – Vectors to upsert. Each element can be a Vector, a tuple of (id, values) or (id, values, metadata), or a dict with id, values, and optional sparse_values / metadata keys.

  • namespace (str) – Target namespace, e.g. "articles-en". Defaults to the index’s default namespace.

  • batch_size (int | None) – Split vectors into chunks of this size and send one request per chunk, e.g. 100. None (default) sends every vector in one request. Must be a positive integer.

  • show_progress (bool) – When True (default) and tqdm is installed, display a progress bar that advances as batches complete. No effect when batch_size is None.

  • max_concurrency (int) – Most batch requests this call keeps in flight at once, e.g. 16. Defaults to 8. Only used when batch_size is set. A process-wide limit per host also applies and holds concurrency lower when the host pushes back; see Bulk ingest.

  • timeout (float | None) – Timeout in seconds for one attempt of one request, e.g. 30.0. A batch is retried on its own under the client’s retry policy, so this does not bound the whole call. None (default) uses the client-level default.

  • total_timeout (float | None) – Deadline in seconds for the whole batched operation, e.g. 600.0. Only used when batch_size is set. On expiry no further batches are submitted, batches already in flight are awaited, and unsent batches are reported in failed_items. None (default) means no deadline. Zero or a negative value raises PineconeValueError.

Returns:

UpsertResponse with upserted_count. With batch_size set, a failed batch does not raise: has_errors, errors and failed_items report what did not land, and failed_items can be passed straight back to upsert(). response_info then carries the aggregate LSN of the successful batches, or None if no LSN headers came back.

Raises:
  • PineconeTypeError – If a vector element is not one of the forms listed above.

  • PineconeValueError – If a vector element is malformed, batch_size is not a positive integer, or max_concurrency is out of range.

  • PayloadTooLargeError – If batch_size is None and the request exceeds the server’s cap on encoded size. Set a batch_size and retry.

  • ApiError – If batch_size is None and the request exceeds the server’s cap on vectors per request.

Return type:

UpsertResponse

Examples

All three vector forms are interchangeable within one call. The values below are truncated to three floats for the page; pass your index’s full dimension.

from pinecone import Vector

response = await idx.upsert(
    vectors=[
        Vector(id="article-101", values=[0.012, -0.087, 0.153]),
        ("article-102", [0.045, 0.021, -0.064]),
        {"id": "article-103", "values": [0.091, -0.032, 0.178]},
    ],
    namespace="articles-en",
)
print(response.upserted_count)

For a sequence too long for one request (embeddings below being your whole list of vectors), set batch_size and resend what did not land:

response = await idx.upsert(
    vectors=embeddings,
    namespace="articles-en",
    batch_size=100,
)
if response.has_errors:
    await idx.upsert(vectors=response.failed_items, namespace="articles-en")

See also

async upsert_from_dataframe(df, namespace=None, batch_size=500, show_progress=True, timeout=None, *, max_concurrency=None, total_timeout=None, on_error=None)[source]

Upsert vectors from a pandas DataFrame, in batches.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use documents instead. Each row becomes one vector, and the rows are sent through upsert() with batch_size set, so a batch that fails is reported on the response rather than raised unless you pass on_error="raise". pandas is not an SDK dependency; install it yourself.

Parameters:
  • df (pd.DataFrame) – A pandas.DataFrame with id and values columns and, optionally, sparse_values and metadata columns. A missing cell (None or NaN) in an optional column leaves that field off the vector.

  • namespace (str | None) – Target namespace, e.g. "articles-en". None (default) targets the index’s default namespace.

  • batch_size (int) – Rows per upsert request, e.g. 100. Defaults to 500. Lower it for wide vectors or large metadata.

  • show_progress (bool) – When True (default) and tqdm is installed, display a progress bar that advances as batches complete.

  • timeout (float | None) – Timeout in seconds for one attempt of one batch’s request, e.g. 30.0. A batch is retried on its own under the client’s retry policy, so this does not bound the whole call. None (default) uses the client-level default.

  • max_concurrency (int | None) – Most batch requests this call keeps in flight at once, e.g. 16. None (default) uses 8. A process-wide limit per host also applies and holds concurrency lower when the host pushes back; see Bulk ingest.

  • total_timeout (float | None) – Deadline in seconds for the whole ingest, e.g. 600.0. On expiry no further batches are submitted, batches already in flight are awaited, and unsent rows are reported in failed_items. None (default) means no deadline. Zero or a negative value raises PineconeValueError.

  • on_error (str | None) – What to do when some batches fail. "collect" (None behaves the same) returns the response with errors and failed_items filled in. This holds when every batch fails too: nothing raises, so check response.has_errors. "raise" raises the lowest-indexed batch failure once every batch has settled, with the partial response on the exception’s response attribute.

Returns:

UpsertResponse with upserted_count totalled across the batches that landed, plus has_errors, errors and failed_items for the ones that did not. failed_items can be passed straight back to upsert().

Raises:
  • RuntimeError – If pandas is not installed.

  • PineconeValueError – If df is not a pandas.DataFrame or lacks an id or values column, batch_size is not a positive integer, max_concurrency is out of range, or on_error is not "collect" or "raise".

  • PineconeTimeoutError – If on_error="raise" and a batch exhausted its retries on timeout.

Return type:

UpsertResponse

Examples

A metadata column is optional; where it is present its dict lands on the vector as written. The values below are truncated to three floats for the page; pass your index’s full dimension.

import pandas as pd

df = pd.DataFrame([
    {
        "id": "article-101",
        "values": [0.012, -0.087, 0.153],
        "metadata": {"topic": "science", "year": 2024},
    },
    {
        "id": "article-102",
        "values": [0.045, 0.021, -0.064],
        "metadata": {"topic": "technology", "year": 2024},
    },
])
response = await idx.upsert_from_dataframe(
    df,
    namespace="articles-en",
    batch_size=100,
)
if response.has_errors:
    await idx.upsert(vectors=response.failed_items, namespace="articles-en")

See also

  • upsert(): the same batched write from a list of vectors, with no pandas dependency.

  • start_import(): millions of vectors from cloud storage, server-side and asynchronous.

async query(*, top_k, vector=None, id=None, namespace='', filter=None, include_values=False, include_metadata=False, sparse_vector=None, scan_factor=None, max_candidates=None, timeout=None)[source]

Query a namespace for the nearest neighbors of a vector you supply.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use documents instead. You supply the query vector; nothing is embedded for you. Pass a dense vector, a sparse_vector, both for a hybrid query, or the id of a stored vector to use as the query.

Parameters:
  • top_k (int) – Number of results to return, e.g. 5. The server caps it.

  • vector (list[float] | None) – Dense query vector, at your index’s dimension.

  • id (str | None) – ID of a stored vector to use as the query, e.g. "article-101". Cannot be combined with vector or sparse_vector.

  • namespace (str) – Namespace to query, e.g. "articles-en". Defaults to the index’s default namespace.

  • filter (dict[str, Any] | None) – Metadata filter expression restricting which vectors are searched, e.g. {"year": {"$gte": 2020}}.

  • include_values (bool) – Return each match’s vector values. False (default) keeps the response small.

  • include_metadata (bool) – Return each match’s metadata. Set it when you need the fields you filtered on back in the result.

  • sparse_vector (SparseValues | dict[str, Any] | None) – Sparse query vector with indices and values, e.g. {"indices": [17, 42], "values": [0.4, 0.9]}. Combine it with vector for a hybrid query on a dense index with the dotproduct metric.

  • scan_factor (float | None) – Recall/latency trade for dense indexes on dedicated read nodes: a multiplier on how much of the index is scanned. Above 1 scans more and favors recall; below 1 scans less and favors latency. Omit to let the server choose.

  • max_candidates (int | None) – Recall/latency trade for dense indexes on dedicated read nodes: caps how many candidates are reranked before top_k is taken. Must be at least top_k.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

QueryResponse with matches (ordered from most to least similar, each carrying id and score), namespace, and usage.

Raises:
  • PineconeValueError – If top_k is not positive or exceeds the server’s maximum, if id is combined with vector or sparse_vector, if none of vector, id, or sparse_vector is given, or if id is not a legal vector ID. Raised before any request is sent.

  • ApiError – If scan_factor or max_candidates is set on an index that does not run on dedicated read nodes, or on a sparse index.

Return type:

QueryResponse

Examples

Query vectors are truncated to three floats on this page; pass your index’s full dimension.

response = await idx.query(
    top_k=5,
    vector=[0.012, -0.087, 0.153],
    namespace="articles-en",
)
for match in response.matches:
    print(match.id, match.score)

A filter narrows the search before ranking, and include_metadata returns the fields it selected on:

response = await idx.query(
    top_k=5,
    vector=[0.012, -0.087, 0.153],
    namespace="movies-en",
    filter={"genre": "comedy", "year": {"$gte": 2020}},
    include_metadata=True,
)
for match in response.matches:
    print(match.id, match.score, match.metadata["genre"])

See also

  • search(): the same search on a legacy integrated index, where you pass text and the server embeds it.

  • query_namespaces(): the same query fanned out over several namespaces, merged into one ranking.

async query_namespaces(*, vector=None, namespaces, metric, top_k=None, filter=None, include_values=False, include_metadata=False, sparse_vector=None, scan_factor=None, max_candidates=None, timeout=None)[source]

Query several namespaces at once and merge them into one ranking.

Serves indexes created with dimension/metric and legacy integrated indexes. Runs one query() per namespace concurrently, then merges the results so you get the overall top-k rather than top-k per namespace. The merge ranks by metric, which the client does not read off the index, so pass the metric the index was created with.

Parameters:
  • vector (list[float] | None) – Dense query vector. Omit it on a sparse index and pass sparse_vector instead.

  • namespaces (list[str]) – Namespaces to query, e.g. ["articles-en", "articles-fr"]. Must be non-empty; duplicates are removed while preserving order.

  • metric (str) – Metric the index was created with: "cosine", "euclidean", or "dotproduct". A wrong metric is not rejected; the merged ranking just comes out in the wrong order.

  • top_k (int | None) – Number of results to return after merging, e.g. 10. Defaults to 10. Each namespace is queried for this many.

  • filter (dict[str, Any] | None) – Metadata filter expression applied to every namespace, e.g. {"year": {"$gte": 2020}}.

  • include_values (bool) – Return each match’s vector values.

  • include_metadata (bool) – Return each match’s metadata.

  • sparse_vector (SparseValues | dict[str, Any] | None) – Sparse query vector with indices and values. Required on a sparse index, where vector is omitted.

  • scan_factor (float | None) – Recall/latency trade for dense indexes on dedicated read nodes, applied to every namespace. See query().

  • max_candidates (int | None) – Candidate cap for dense indexes on dedicated read nodes, applied per namespace. Must be at least top_k.

  • timeout (float | None) – Per-request timeout in seconds, applied to each namespace’s query rather than to the call as a whole.

Returns:

QueryNamespacesResults with the merged matches, usage totalled over every namespace, and ns_usage keyed by namespace name. A match does not record which namespace produced it, so query one namespace at a time when you need that.

Raises:
  • PineconeValueError – If namespaces is empty, if both vector and sparse_vector are absent or empty, or if metric is not one of "cosine", "euclidean", or "dotproduct". Raised before any request is sent.

  • ApiError – If any one namespace’s query fails. The first failure propagates and the merged result is lost, so retry the whole call.

Return type:

QueryNamespacesResults

Examples

The query vector is truncated to three floats on this page; pass your index’s full dimension.

results = await idx.query_namespaces(
    vector=[0.012, -0.087, 0.153],
    namespaces=["articles-en", "articles-fr", "articles-de"],
    metric="cosine",
    top_k=10,
)
for match in results.matches:
    print(match.id, match.score)

On a sparse index, pass sparse_vector instead and rank by "dotproduct":

results = await idx.query_namespaces(
    sparse_vector={"indices": [17, 42, 108], "values": [0.4, 0.9, 0.2]},
    namespaces=["articles-en", "articles-fr"],
    metric="dotproduct",
    top_k=10,
)

See also

query(): one namespace, and the only form that takes an id as the query.

async fetch(*, ids, namespace='', timeout=None)[source]

Fetch vectors by their IDs, exactly as stored.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use documents instead. A lookup, not a search: nothing is ranked and no score is returned. An ID that is not in the namespace is silently absent from the result, so compare the keys you got back against the ones you asked for.

Parameters:
  • ids (list[str]) – Vector IDs to fetch, e.g. ["article-101", "article-102"]. Must be non-empty.

  • namespace (str) – Namespace to fetch from, e.g. "articles-en". Defaults to the index’s default namespace.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

FetchResponse with vectors, a map of ID to Vector holding values and metadata as stored, plus namespace and usage. IDs the namespace does not hold are absent from the map rather than raising.

Raises:

PineconeValueError – If ids is empty or holds an ID that is empty, non-ASCII, contains a NUL, or is longer than the API allows. Raised before any request is sent.

Return type:

FetchResponse

Examples

wanted = ["article-101", "article-102"]
response = await idx.fetch(ids=wanted, namespace="articles-en")
for vid, vec in response.vectors.items():
    print(vid, vec.metadata)
print("not in this namespace:", set(wanted) - set(response.vectors))

See also

  • fetch_by_metadata(): when you know the metadata you want rather than the IDs.

  • query(): when you want the nearest vectors rather than named ones.

async fetch_by_metadata(*, filter, namespace='', limit=None, pagination_token=None, timeout=None)[source]

Fetch one page of the vectors whose metadata matches a filter.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use documents instead. A lookup, not a search: matches are not ranked and carry no score. One page is returned per call, so follow pagination.next to reach the rest.

Parameters:
  • filter (dict[str, Any]) – Metadata filter expression, e.g. {"year": {"$gte": 2020}}. Must carry at least one condition; an empty filter is rejected rather than treated as “match everything”.

  • namespace (str) – Namespace to fetch from, e.g. "movies-en". Defaults to the index’s default namespace.

  • limit (int | None) – Maximum number of vectors in this page, e.g. 100. Omit to let the server choose the page size.

  • pagination_token (str | None) – pagination.next from the previous response. None (default) fetches the first page.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

FetchByMetadataResponse with vectors as stored, plus namespace, usage, and pagination, which holds the next page’s token in next and is None on the last page.

Raises:

PineconeValueError – If filter is empty or limit is not a positive integer within the API’s maximum page size. Raised before any request is sent.

Return type:

FetchByMetadataResponse

Examples

response = await idx.fetch_by_metadata(
    filter={"genre": "comedy", "year": {"$gte": 2020}},
    namespace="movies-en",
)
for vid, vec in response.vectors.items():
    print(vid, vec.metadata)

See also

  • fetch(): when you already know the IDs.

  • query(): when you want the nearest vectors to a query rather than every vector a filter admits.

  • Pagination: walking every page.

async delete(*, ids=None, delete_all=False, filter=None, namespace='', timeout=None)[source]

Delete vectors from a namespace by ID, by filter, or all of them.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use documents instead. Pass exactly one selector: ids, filter, or delete_all=True. The delete is irreversible, and IDs the namespace does not hold are ignored rather than reported, so a successful call is not evidence anything was deleted.

Parameters:
  • ids (list[str] | None) – Vector IDs to delete, e.g. ["article-101", "article-102"].

  • delete_all (bool) – Delete every vector in namespace. The namespace itself survives; delete_namespace() removes that too.

  • filter (dict[str, Any] | None) – Metadata filter expression selecting what to delete, e.g. {"status": {"$eq": "retracted"}}. Must carry at least one condition. The client refuses ids alongside filter, because the server would apply the filter alone and delete everything it matches rather than the intersection; to delete the intersection, query() with the filter first and delete the IDs you get back.

  • namespace (str) – Namespace to delete from, e.g. "articles-en". Defaults to the index’s default namespace.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

None. A successful delete returns no payload.

Raises:

PineconeValueError – If zero or more than one selector is given, if filter is empty, or if an ID is not a legal vector ID. Raised before any request is sent.

Return type:

None

Examples

By ID:

await idx.delete(
    ids=["article-101", "article-102"],
    namespace="articles-en",
)

By metadata filter, which deletes every vector the filter admits:

await idx.delete(
    filter={"status": {"$eq": "retracted"}},
    namespace="articles-en",
)

Emptying a whole namespace cannot be undone:

await idx.delete(delete_all=True, namespace="articles-staging")

See also

delete_namespace(): removes the namespace along with everything in it, where delete_all=True empties it and leaves it in place.

async update(*, id=None, values=None, sparse_values=None, set_metadata=None, namespace='', filter=None, dry_run=False, timeout=None)[source]

Patch one vector by ID, or patch metadata across a filter.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use documents instead. A partial update: fields you do not mention keep the values they had, so set_metadata={"year": 2021} leaves every other metadata key in place. Pass exactly one selector, id or filter; a by-filter update is metadata-only, since values and sparse_values belong to one record. The write applies asynchronously, so a read straight afterwards can still see the old value.

Parameters:
  • id (str | None) – ID of the one vector to patch, e.g. "article-101".

  • values (list[float] | None) – Replacement dense values, at your index’s dimension. Only with id.

  • sparse_values (SparseValues | dict[str, Any] | None) – Replacement sparse vector, with indices and values. Only with id.

  • set_metadata (dict[str, Any] | None) – Metadata keys to set or overwrite, e.g. {"year": 2021}. Keys you omit are left as they are; this never clears a field.

  • namespace (str) – Namespace to target, e.g. "movies-en". Defaults to the index’s default namespace.

  • filter (dict[str, Any] | None) – Metadata filter expression selecting which vectors to patch, e.g. {"genre": {"$eq": "drama"}}. Must carry at least one condition.

  • dry_run (bool) – Report how many records the filter would touch without writing anything. Ignored for a by-ID update. Run it first when the filter is broader than you can check by eye.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

UpdateResponse whose matched_records counts the records the filter matched, which under dry_run are the records that would have been patched. It is None for a by-ID update, which reports no count.

Raises:

PineconeValueError – If both or neither of id and filter are given, if filter is combined with values or sparse_values, if filter is empty, or if id is not a legal vector ID. Raised before any request is sent.

Return type:

UpdateResponse

Examples

Replacing one vector’s values, truncated here to three floats:

await idx.update(
    id="article-101",
    values=[0.012, -0.087, 0.153],
    namespace="articles-en",
)

Patching metadata across a filter. dry_run reports the reach first, and the genre of every patched record survives untouched:

preview = await idx.update(
    filter={"genre": {"$eq": "drama"}},
    set_metadata={"reviewed": True},
    namespace="movies-en",
    dry_run=True,
)
print(preview.matched_records)
await idx.update(
    filter={"genre": {"$eq": "drama"}},
    set_metadata={"reviewed": True},
    namespace="movies-en",
)

See also

upsert(): replaces a whole vector rather than patching it, and creates it if the ID is new.

async search(*, namespace, top_k=None, inputs=None, vector=None, id=None, filter=None, fields=None, rerank=None, match_terms=None, query=None, timeout=None)[source]

Search records by text, vector, or ID, optionally reranking (legacy Records API).

Give exactly one query source. Text in inputs needs a legacy integrated index, created with create_for_model(), whose model embeds it server-side. A vector or id query also works on an index created with dimension/metric, though query() is the usual call there. On a document index use documents instead.

Parameters:
  • namespace (str) – Namespace to search, e.g. "articles-en". Required: pass "__default__" to search the default namespace.

  • top_k (int) – Number of results to return, at least 1, e.g. 10. Required unless query is given.

  • inputs (SearchInputs | dict[str, Any] | None) – Text for the index’s model to embed, e.g. {"text": "trail running shoes"}. SearchInputs gives typed keys and IDE completion.

  • vector (list[float] | dict[str, Any] | None) – Query vector. A list[float] is a dense query; a dict with values, sparse_indices and/or sparse_values is a sparse or hybrid one. SearchQueryVector is the typed helper.

  • id (str | None) – ID of a stored record whose vector is the query, e.g. "article-101".

  • filter (dict[str, Any] | None) – Metadata filter, e.g. {"category": {"$eq": "footwear"}}.

  • fields (list[str] | None) – Record fields to return in each hit, e.g. ["title", "text"]. None returns every stored field.

  • rerank (RerankConfig | dict[str, Any] | None) – Rerank the hits in the same call. Needs model and rank_fields; top_n, parameters and query are optional. RerankConfig gives IDE completion.

  • match_terms (dict[str, Any] | None) – Require hits to contain query terms, e.g. {"strategy": "all", "terms": ["running", "shoes"]}. Valid only with inputs, on a sparse index whose model supports it; the server names the supported model when it refuses.

  • timeout (float | None) – Per-request timeout in seconds, e.g. 10.0. Overrides the client-level default for this call only.

  • query (SearchQuery | dict[str, Any] | None) – The older nested form of this call: top_k plus one query source in one mapping. Pass the fields directly instead.

Returns:

SearchRecordsResponse whose result.hits run from most to least relevant. Read each Hit as hit.id, hit.score and hit.fields. usage reports read units, plus embedding tokens and rerank units when those stages ran.

Raises:
  • PineconeValueError – If namespace is not a non-empty string, top_k is missing or below 1, no query source is given, a vector dict has an unsupported key, or rerank lacks model or rank_fields. Raised before any request is made.

  • TypeError – If query is combined with any of the flat keyword arguments it replaces (top_k, inputs, vector, id, filter, match_terms), so pass one form or the other, not both; or if query is neither a SearchQuery nor a mapping.

Return type:

SearchRecordsResponse

Examples

Text in, embedded server-side. The hits nest one level down, under result:

response = await idx.search(
    namespace="articles-en",
    top_k=10,
    inputs={"text": "benefits of vector databases for search"},
    fields=["title", "text"],
)
for hit in response.result.hits:
    print(hit.id, hit.score, hit.fields["title"])

Reranking in the same call retrieves top_k hits and returns the top_n the reranker scores highest:

response = await idx.search(
    namespace="articles-en",
    top_k=50,
    inputs={"text": "benefits of vector databases"},
    rerank={
        "model": "bge-reranker-v2-m3",
        "rank_fields": ["text"],
        "top_n": 5,
    },
)

See also

  • query(): search with a vector you embedded yourself.

  • Inference.rerank(): rerank results that came from somewhere other than this index.

async search_records(*, namespace, top_k=None, inputs=None, vector=None, id=None, filter=None, fields=None, rerank=None, match_terms=None, query=None, timeout=None)[source]

Alias for search() (legacy Records API), kept for callers written against 9.x.

Every argument, return value and error is search()’s. Call that one in new code.

Parameters:
Return type:

SearchRecordsResponse

async list_paginated(*, prefix=None, limit=None, pagination_token=None, namespace='', timeout=None)[source]

Fetch one page of vector IDs, holding the pagination token yourself.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use documents instead. Returns IDs only, without values or metadata. list() walks the pages for you; use this one when you need to keep the token between calls.

Parameters:
  • prefix (str | None) – Return only IDs starting with this prefix, e.g. "article-2024#". Must be ASCII, without a NUL character, and no longer than the API allows. The empty prefix matches everything.

  • limit (int | None) – Maximum number of IDs in this page, e.g. 50. Must be a positive integer within the API’s maximum page size. None uses the server’s default page size.

  • pagination_token (str | None) – pagination.next from the previous response. None (default) fetches the first page.

  • namespace (str) – Namespace to list from, e.g. "articles-en". Defaults to the default namespace.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

ListResponse whose vectors are ListItem entries carrying only an id, plus namespace, usage, and pagination. pagination.next is the token for the following page; the last page carries no token.

Raises:

PineconeValueError – If prefix or limit is not legal. Raised before any request is sent.

Return type:

ListResponse

Examples

response = await idx.list_paginated(
    prefix="article-2024#",
    limit=50,
    namespace="articles-en",
)
for item in response.vectors:
    print(item.id)
next_token = response.pagination.next if response.pagination else None

See also

  • list(): the same listing with the token handled for you.

  • fetch(): the vectors behind those IDs.

  • Pagination: how the SDK pages generally.

list(*, prefix=None, limit=None, namespace='', timeout=None)[source]

List vector IDs in a namespace, a page at a time.

Serves indexes created with dimension/metric and legacy integrated indexes; on a document index use documents instead. Returns IDs only, without values or metadata. Yields one page per iteration and follows the pagination tokens itself. Nothing is requested until you iterate, so a bad prefix or limit is not reported until then either.

Parameters:
  • prefix (str | None) – Return only IDs starting with this prefix, e.g. "article-2024#". Must be ASCII, without a NUL character, and no longer than the API allows. The empty prefix matches everything.

  • limit (int | None) – Maximum number of IDs per page, e.g. 50. Must be a positive integer within the API’s maximum page size. None uses the server’s default page size.

  • namespace (str) – Namespace to list from, e.g. "articles-en". Defaults to the default namespace.

  • timeout (float | None) – Per-request timeout in seconds, applied to each underlying page request. Overrides the client-level default for this call only.

Yields:

ListResponse per page, whose vectors carry the IDs. A page with no IDs is skipped rather than yielded.

Raises:

PineconeValueError – If prefix or limit is not legal. Raised on first iteration, not at the call.

Return type:

AsyncIterator[ListResponse]

Examples

async for page in idx.list(prefix="article-2024#", namespace="articles-en"):
    ids = [item.id for item in page.vectors]
    fetched = await idx.fetch(ids=ids, namespace="articles-en")
    for vid, vec in fetched.vectors.items():
        print(vid, vec.metadata)

See also

async describe_index_stats(*, filter=None, timeout=None)[source]

Report vector counts per namespace, dimension, and fullness for this index.

Works on every kind of index, including document indexes. The counts lag writes, so a record just upserted may not be counted yet.

Parameters:
  • filter (dict[str, Any] | None) – Accepted for API compatibility only. The server rejects a non-empty filter, so leave it unset; the statistics always describe the whole index.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

Returns:

DescribeIndexStatsResponse with total_vector_count, dimension, index_fullness, and namespaces, which maps each namespace name to a NamespaceSummary carrying its vector_count. The default namespace appears under "__default__".

Raises:

ApiError – If filter is non-empty.

Return type:

DescribeIndexStatsResponse

Examples

stats = await idx.describe_index_stats()
print(stats.dimension, stats.index_fullness)
for name, summary in stats.namespaces.items():
    print(name, summary.vector_count)

See also

list_namespaces(): per-namespace record counts alongside each namespace’s schema and size_bytes.

async create_namespace(*, name, schema=None)[source]

Create a named namespace in the index.

Optional: upserting into a name that does not exist yet creates the namespace. Create one explicitly when it must exist before any data lands in it, or to choose which metadata fields it indexes. Not idempotent: an existing name raises ConflictError.

Parameters:
  • name (str) – Name for the new namespace, e.g. "movies-en". Must be non-empty ASCII without the NUL character, and no longer than the API’s maximum name length. __default__ is reserved and cannot be created. On an index created with dimension/metric it names the namespace requests address when they omit one, which always exists; on a document index, upserting documents into __default__ creates it.

  • schema (dict[str, Any] | None) – Optional metadata-index configuration, {"fields": {<field>: {"filterable": True}}}. Omitting it does not mean “index everything”: the namespace inherits the index’s own metadata-index configuration. Supply schema to index exactly the fields listed in this namespace. Each field must set filterable to True; to leave a field unindexed, omit it from fields.

Returns:

NamespaceDescription with the namespace name, record_count, schema, indexed_fields and size_bytes.

Raises:
  • PineconeValueError – If name violates the rules above, or schema is malformed. Raised before any request is sent.

  • ConflictError – a namespace of that name already exists.

Return type:

NamespaceDescription

Examples

ns = await idx.create_namespace(name="movies-en")
print(ns.name, ns.record_count, ns.size_bytes)

Naming the filterable fields up front overrides what the namespace would otherwise inherit from the index:

ns = await idx.create_namespace(
    name="movies-fr",
    schema={"fields": {"genre": {"filterable": True}}},
)
print(ns.indexed_fields)

See also

async describe_namespace(*, name=None, **kwargs)[source]

Describe a namespace by name.

Rate limited per index. To describe more than one namespace, use list_namespaces(), which returns a whole page of descriptions per request.

Parameters:
  • name (str) – Name of the namespace to describe, e.g. "movies-en". Must be non-empty ASCII without the NUL character, and no longer than the API’s maximum name length. On an index created with dimension/metric, pass __default__ to describe the namespace requests address when they omit one. On a document index __default__ is an ordinary name, so describing it raises NotFoundError until documents are upserted into it.

  • kwargs (str)

Returns:

NamespaceDescription with the namespace name, record_count, schema, indexed_fields and size_bytes. size_bytes is approximate.

Raises:
Return type:

NamespaceDescription

Examples

ns = await idx.describe_namespace(name="movies-en")
print(ns.name, ns.record_count, ns.size_bytes)

On an index created with dimension/metric, the namespace that unnamespaced requests address answers to __default__:

ns = await idx.describe_namespace(name="__default__")
print(ns.record_count)

See also

list_namespaces(): every namespace, a page of descriptions per request.

async delete_namespace(*, name=None, timeout=None, **kwargs)[source]

Delete a namespace and everything in it.

Irreversible: every record in the namespace is deleted, and the namespace itself stops existing. To empty a namespace but keep it, use delete() with delete_all=True.

Parameters:
  • name (str) – Name of the namespace to delete, e.g. "movies-deprecated". Must be non-empty ASCII without the NUL character, and no longer than the API’s maximum name length.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only.

  • kwargs (str)

Returns:

None. A successful delete returns no payload.

Raises:
  • PineconeValueError – If name violates the rules above. Raised before any request is sent.

  • TypeError – If unexpected keyword arguments are passed.

  • NotFoundError – no namespace of that name exists on the index.

Return type:

None

Examples

await idx.delete_namespace(name="movies-deprecated")

See also

delete(): delete_all=True empties a namespace and leaves it in place.

async list_namespaces_paginated(*, prefix=None, limit=None, pagination_token=None)[source]

Fetch one page of namespace descriptions, holding the token yourself.

list_namespaces() walks the pages for you; reach for this one when you need to persist the token between calls or hand it to a caller of your own.

Parameters:
  • prefix (str | None) – Return only namespaces whose names start with this prefix, e.g. "movies-". Same character rules as namespace names; the empty prefix matches every namespace.

  • limit (int | None) – Maximum number of namespaces in this page, e.g. 50. None (default) lets the server choose.

  • pagination_token (str | None) – pagination.next from the previous response. None (default) fetches the first page.

Returns:

ListNamespacesResponse with namespaces (each a NamespaceDescription), total_count across every page, and pagination, whose next is None on the last page.

Raises:

PineconeValueError – If prefix or limit is out of range. Raised before any request is sent.

Return type:

ListNamespacesResponse

Examples

response = await idx.list_namespaces_paginated(prefix="movies-", limit=10)
for ns in response.namespaces:
    print(ns.name, ns.record_count, ns.size_bytes)
next_token = response.pagination.next if response.pagination else None

See also

list_namespaces(*, prefix=None, limit=None)[source]

List every namespace, a page at a time.

Yields one ListNamespacesResponse per page and follows the pagination tokens itself, so nothing is requested until you iterate. Each page describes many namespaces in one request, so prefer this over repeated describe_namespace() calls, which are rate limited per index.

Parameters:
  • prefix (str | None) – Return only namespaces whose names start with this prefix, e.g. "movies-". Same character rules as namespace names; the empty prefix matches every namespace.

  • limit (int | None) – Maximum number of namespaces per page, e.g. 50. None (default) lets the server choose.

Yields:

ListNamespacesResponse per page, each carrying namespaces of NamespaceDescription. A page with no namespaces is skipped rather than yielded.

Raises:

PineconeValueError – If prefix or limit is out of range. Raised on first iteration, not at the call.

Return type:

AsyncIterator[ListNamespacesResponse]

Examples

async for page in idx.list_namespaces(prefix="movies-"):
    for ns in page.namespaces:
        print(ns.name, ns.record_count, ns.size_bytes)

See also

async start_import(uri, *, error_mode=None, integration_id=None)[source]

Start a server-side bulk import of vectors from cloud storage.

Returns as soon as the server accepts the import, not when it finishes: poll describe_import() for the outcome. Imports work on indexes created with dimension/metric and on document indexes; the server refuses them on an index with integrated embedding (a legacy integrated index, or a document index with an embed field).

Parameters:
  • uri (str) – Directory prefix holding the Parquet files, not a single file. Three forms are accepted: s3:// for Amazon S3, gs:// for Google Cloud Storage, and an https:// URL naming an Azure Blob Storage container. s3:// additionally requires that the index itself be hosted on AWS.

  • error_mode (str | None) – How to handle a record the import cannot read. "continue" skips it and imports the rest; "abort" ends the whole import at the first such record. Case-insensitive. Defaults to "abort" when omitted, so an unreadable record fails the import unless you opt into skipping.

  • integration_id (str | None) – ID of a storage integration in your project that grants Pinecone read access to a private bucket. Its cloud provider must match the scheme of uri.

Returns:

StartImportResponse with id, the handle the other import methods take.

Raises:
  • PineconeValueError – If error_mode is supplied but is neither "continue" nor "abort". Raised before any HTTP request is made.

  • ApiError – If the server rejects uri (for example, an s3:// URI on an index not hosted on AWS) or the index uses integrated embedding.

Return type:

StartImportResponse

Examples

Starting an import and waiting it out is on you; three of the five statuses are terminal:

import asyncio

response = await idx.start_import(uri="s3://article-embeddings/2024/")
import_op = await idx.describe_import(response.id)
while import_op.status not in ("Completed", "Failed", "Cancelled"):
    await asyncio.sleep(10)
    import_op = await idx.describe_import(response.id)
print(import_op.status, import_op.records_imported)

error_mode="continue" finishes the import around records it cannot read, rather than stopping at the first one:

response = await idx.start_import(
    uri="s3://article-embeddings/2024/",
    error_mode="continue",
)

Note

uri must name a directory of Parquet files following Pinecone’s import schema. See the import guide for that schema and the supported storage formats.

See also

async describe_import(id)[source]

Describe a bulk import operation by ID.

Parameters:

id (str | int) – The id start_import() returned, e.g. "1". An int is accepted and converted to a string.

Returns:

ImportModel with status ("Pending", "InProgress", "Failed", "Completed", or "Cancelled"; the last three are terminal), percent_complete, records_imported, uri, and error when it failed.

Raises:
Return type:

ImportModel

Examples

import_op = await idx.describe_import("1")
print(import_op.status, import_op.percent_complete)
if import_op.status == "Failed":
    print(import_op.error)

See also

  • start_import(): starts an import and returns the id these methods take.

  • list_imports(): every import on the index, when you do not have an id.

async cancel_import(id)[source]

Cancel a bulk import operation by ID.

Parameters:

id (str | int) – The id start_import() returned, e.g. "1". An int is accepted and converted to a string.

Returns:

None. Poll describe_import() to see the import reach "Cancelled".

Raises:
Return type:

None

Examples

await idx.cancel_import("1")

See also

  • start_import(): starts an import and returns the id these methods take.

  • list_imports(): every import on the index, when you do not have an id.

list_imports(*, limit=None, pagination_token=None)[source]

List every bulk import on this index, following pagination.

Yields ImportModel objects rather than pages, and fetches the next page as you exhaust the current one, so nothing is requested until you iterate. See Pagination.

Parameters:
  • limit (int | None) – Maximum number of imports per page, e.g. 10. Omit to let the server choose the page size.

  • pagination_token (str | None) – Token to resume from, when you are continuing a listing rather than starting one.

Yields:

ImportModel for each import operation.

Raises:

ApiError – If a page request fails part-way through the listing; the imports already yielded are still yours, the rest are not.

Return type:

AsyncIterator[ImportModel]

Examples

async for imp in idx.list_imports():
    print(imp.id, imp.status, imp.uri)

See also

async list_imports_paginated(*, limit=None, pagination_token=None)[source]

Fetch one page of bulk imports, holding the token yourself.

list_imports() walks the pages for you; use this one when you need to persist the token between calls. See Pagination.

Parameters:
  • limit (int | None) – Maximum number of imports in this page, e.g. 10.

  • pagination_token (str | None) – pagination.next from the previous response. None (default) fetches the first page.

Returns:

ImportList you can iterate for this page’s ImportModel objects, with pagination.next holding the token for the following page or None on the last one.

Return type:

ImportList

Examples

page = await idx.list_imports_paginated(limit=10)
for imp in page:
    print(imp.id, imp.status)
next_token = page.pagination.next if page.pagination else None

See also

async close()[source]

Close the underlying HTTP client and release its resources.

Calls on a closed index fail. Prefer async with over calling this by hand, which closes the client even if the body raises.

Returns:

None.

Return type:

None

Examples

async with await pc.index(name="article-search") as idx:
    await idx.upsert(
        vectors=[("article-101", [0.012, -0.087, 0.153])],
        namespace="articles-en",
    )
async __aenter__()[source]

Enter the async context manager, returning this index.

Returns:

This AsyncIndex instance.

Return type:

AsyncIndex

Examples

async with await pc.index(name="article-search") as idx:
    await idx.upsert(
        vectors=[("article-101", [0.012, -0.087, 0.153])],
        namespace="articles-en",
    )
async __aexit__(*args)[source]

Exit the async context manager, calling close().

Returns:

None.

Parameters:

args (Any)

Return type:

None

AsyncDocuments

class pinecone.async_client.documents.AsyncDocuments(*, http, host)[source]

Bases: object

Document data-plane operations for a schema-based index.

A schema-based index stores JSON documents instead of raw vectors. Every document carries the reserved _id key; every other key is a field of your own, either declared in the index schema or free-form metadata. Accessed via documents. Not constructed directly; the parent AsyncIndex builds and caches its own instance on first access.

On a vector-based index, use the vector methods on AsyncIndex itself (upsert(), query()) rather than this namespace. Every method here is keyword-only. A positional argument raises PineconeValueError listing the accepted keywords, and a misspelled keyword raises TypeError suggesting the one you meant.

Examples

On an index whose schema declares embedding as a 1536-dimension dense_vector and title as a full-text string:

from pinecone import AsyncPinecone

pc = AsyncPinecone(api_key="your-api-key")
idx = await pc.index(name="articles-en")
async with idx:
    await idx.documents.upsert(
        namespace="published",
        documents=[
            {
                "_id": "article-101",
                "embedding": [0.1] * 1536,
                "title": "Intro to vectors",
            }
        ],
    )

See also

Error handling: the exceptions any of these methods can raise, and which ones are worth retrying.

Parameters:
  • http (AsyncHTTPClient)

  • host (str)

__init__(*, http, host)[source]
Parameters:
  • http (AsyncHTTPClient)

  • host (str)

Return type:

None

async upsert(*, namespace, documents, timeout=None)[source]

Upsert documents into a namespace.

Each document must include an _id field (a unique, non-empty ASCII string). If a document with the same _id already exists in the namespace, it is overwritten.

The index schema decides which other fields a document must carry; read it with pc.indexes.describe(name).schema. Every dense_vector field is required, and so is every string field declared with embed, because Pinecone embeds its text on write. sparse_vector fields, string fields with only sparse_embed or full-text search, and metadata are optional. Each document also needs at least one searchable schema field: a vector field, or a string field with full-text search, embed or sparse_embed. The server rejects a document that breaks either rule with a 400 that names the document and the fields it needs.

Pinecone applies the upsert asynchronously, so documents may not be immediately visible to search() or fetch().

Parameters:
  • namespace (str) – Target namespace (required, non-empty).

  • documents (Sequence[Mapping[str, Any] | DocumentRecord]) – The documents to upsert. Each element is a dict with an _id key or a DocumentRecord. The server limits a request by document count (a lower count on an index with an embed or sparse_embed field) and by encoded size, so documents that carry large fields, such as high-dimensional dense vectors, fit fewer per request. For large lists, or documents of unknown size, use batch_upsert(), which handles the size limit.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only. Must be greater than zero.

Returns:

UpsertDocumentsResponse with the count of documents accepted for upsert. usage.embed_total_tokens counts the tokens Pinecone embedded for embed and sparse_embed fields; usage is None when the upsert embedded no text.

Raises:
  • PineconeValueError – If namespace is empty, documents is empty or longer than one request accepts, or any document has a missing, empty, non-string, non-ASCII, overlong, or duplicate _id; the message names the offending document’s position. Also raised if timeout is zero or negative.

  • ApiError – If a document lacks a field its schema requires (400).

  • PayloadTooLargeError – If one request exceeds the server’s cap on encoded request size, which a request within the document-count limit can still do. Send fewer documents per request, or use batch_upsert().

Return type:

UpsertDocumentsResponse

Examples

On an index whose schema declares embedding as a 1536-dimension dense_vector and title as a full-text string, every document carries embedding and title is optional:

response = await idx.documents.upsert(
    namespace="published",
    documents=[
        {"_id": "article-101", "embedding": [0.1] * 1536, "title": "Vector basics"},
        {"_id": "article-102", "embedding": [0.2] * 1536},
    ],
)
print(response.upserted_count)

See also

  • batch_upsert(): for upserting large document lists in parallel batches.

  • upsert(): for indexes where you provide your own vectors.

async batch_upsert(*, namespace, documents, batch_size=50, max_concurrency=None, show_progress=True, timeout=None, total_timeout=None)[source]

Upsert a large list of documents in parallel batches.

Splits documents into chunks of batch_size and submits them through the host’s admission gate. Concurrency is bounded by max_concurrency and by the host’s adaptive concurrency limit, whichever is lower, so a struggling backend applies backpressure instead of being handed every batch at once. Per-batch HTTP failures are captured in the returned BatchResult rather than raised, so one failed batch does not abort the rest; retry only the failures by passing result.failed_items back in.

Requests are limited by encoded size as well as document count. When the server rejects a batch as too large (HTTP 413), the batch is halved and each half resent, recursively, so documents of any size are sent without choosing a batch_size by trial and error. A single document that is itself over the limit cannot be split: it is reported in result.failed_items with retryable=False. A split batch can land in part: failed_items lists only the pieces that were rejected, and several result.errors rows can share one batch_index.

Parameters:
  • namespace (str) – Target namespace (required, non-empty).

  • documents (Sequence[Mapping[str, Any] | DocumentRecord]) – Documents to upsert. Each element is a dict with an _id key or a DocumentRecord; IDs must be unique across the whole list. Each document must also carry every dense_vector field and every string field declared with embed; sparse_vector fields, sparse_embed-only or full-text-only string fields, and metadata are optional, but each document needs at least one searchable schema field (see upsert()). One document that breaks these rules fails its whole batch with a 400, recorded in result.errors with retryable=False; fix the documents before resending.

  • batch_size (int) – Maximum documents per request. Defaults to 50. On an index with an embed or sparse_embed field, the server accepts fewer documents per request, and a batch over that count fails with a 400 instead of being split; the default fits within it. A batch the server rejects as too large by encoded size is halved and resent, so on any other index a batch_size above what fits by size is safe, at the cost of the rejected requests.

  • max_concurrency (int | None) – Upper bound on concurrent requests. None (default) means 8. The admission gate’s adaptive limit for the host applies on top of whatever is passed.

  • show_progress (bool) – Display a progress bar when tqdm is installed. Defaults to True.

  • timeout (float | None) – Per-request timeout in seconds applied to each batch’s request, not to the whole call. Must be greater than zero.

  • total_timeout (float | None) – Deadline in seconds for the whole batched upsert, as opposed to timeout, which bounds a single attempt of a single batch. On expiry no further batches are submitted, and the un-submitted ones are reported in result.failed_items so they can be retried. None (default) means no deadline. See the note below for what result.timed_out does and does not tell you.

Returns:

BatchResult with aggregated success and failure counts. Per-batch server rejections are not raised: each is recorded in result.errors and the affected documents in result.failed_items. A PayloadTooLargeError in result.errors belongs to a single document over the server’s size cap; resending it or lowering batch_size fails the same way, so shrink that document instead.

Raises:

PineconeValueError – If namespace is empty, documents is empty or contains an invalid or duplicate _id, or batch_size or max_concurrency is outside its accepted range. Also raised if timeout or total_timeout is zero or negative.

Return type:

BatchResult

Examples

On an index whose schema declares embedding as a dense_vector and title as a full-text string, where vectors holds one embedding per article:

documents = [
    {"_id": f"article-{i}", "embedding": vector, "title": f"Article {i}"}
    for i, vector in enumerate(vectors)
]
result = await idx.documents.batch_upsert(
    namespace="published",
    documents=documents,
    batch_size=100,
    max_concurrency=8,
    total_timeout=60.0,
)
print(result.successful_item_count, result.failed_item_count)
if result.timed_out:
    result = await idx.documents.batch_upsert(
        namespace="published",
        documents=result.failed_items,
        batch_size=100,
    )

Note

Batches already in flight when total_timeout expires are awaited and never cancelled, because dropping one client-side would not stop the host from applying it. So result.timed_out is True only when something was actually left unsent; if the in-flight batches were the last ones and all landed, the upsert succeeded late rather than failing. Time spent waiting for the host’s admission gate counts against the budget, so a throttled host can consume it without a request being sent.

See also

  • upsert(): for a document list that fits in one request.

  • How bulk ingest behaves: choosing a batch size and concurrency, and reading the gate counters on the result.

async search(*, namespace, score_by, top_k, include_fields=None, filter=None, timeout=None)[source]

Search documents in a namespace using one or more scoring methods.

Ranks documents by the clauses in score_by and returns the top_k best. A clause scores by dense or sparse vector similarity, BM25 text relevance, a Lucene query string, or similarity to query text that Pinecone embeds with the model of a field declared with embed or sparse_embed.

Parameters:
  • namespace (str) – Namespace to search (required, non-empty).

  • score_by (Sequence[TextQuery | QueryStringQuery | DenseVectorQuery | SparseVectorQuery | EmbedQuery | SparseEmbedQuery | Mapping[str, Any]]) – Scoring methods to rank documents by, as a list. Wrap a single clause as [clause]. Items are typed variants (TextQuery, QueryStringQuery, DenseVectorQuery, SparseVectorQuery, EmbedQuery, SparseEmbedQuery) or plain dicts with a type key. A dict clause with a key its type does not define, such as boost, is rejected with a PineconeValueError rather than dropped. text and query_string clauses may be combined; a dense_vector, sparse_vector, embed or sparse_embed clause must appear alone. Combined clauses are OR’d, not AND’d: a document that matches any clause is returned, and one that matches several scores the sum of the scores from each clause it matches. A text clause naming several fields works the same way across those fields. Repeating a clause, naming a field twice, or writing one query as both a text and a query_string clause scores it once, so repeating a clause does not up-weight it. To weight a term, give it a ^N boost in a QueryStringQuery, such as title:entropy^5; a text clause has no boost. To require several terms together, use AND inside one QueryStringQuery.

  • top_k (int) – Number of top-ranked documents to return.

  • include_fields (Sequence[str] | None) – Document fields to include in each match. Omitting it (the default) or passing [] returns only _id and _score; ["*"] returns every field, even alongside other names. fetch() is the opposite: there, omitting the argument returns every field. Naming a field declared with store_text: false is rejected by the server with a 400, since its text is not stored; ["*"] leaves it out.

  • filter (Mapping[str, Any] | None) –

    Filter expression restricting the documents searched, or None. Which operators a predicate may use depends on the field it names:

    • A data field, one the schema declares to be searched (a vector field, or a string declared with full_text_search, embed or sparse_embed), rejects comparison operators such as $eq with a 400. Of these, a string whose text is stored and searchable takes the text-match operators: one declared with full_text_search, or with embed or sparse_embed and the default store_text (the server turns full-text search on for it). A store_text=False string does not, and neither does a vector field. The operators are $match_phrase (the words as a contiguous, ordered phrase), $match_all (every word, in any order) and $match_any (at least one word).

    • A metadata field, one the schema does not declare or declares only for filtering (an integer, float, boolean, string list, or a string with no search configuration), takes the comparison, set and logical operators ($eq, $in, $gte and so on). A text-match operator on it is rejected with a 400.

    The two kinds combine under $and.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only. Must be greater than zero.

Returns:

SearchDocumentsResponse with matches (ordered from most to least similar), namespace, and usage, whose embed_total_tokens counts the query tokens Pinecone embedded when the server reports it. Each match is a Document, reached as doc.id, doc.score, and doc.<field> for the fields include_fields asked for.

Raises:
  • PineconeValueError – If namespace is empty, score_by is empty, has more clauses than one request accepts, or combines a vector, embed or sparse_embed clause with any other clause, or top_k is outside its accepted range. Also raised if timeout is zero or negative.

  • PineconeTypeError – If top_k is not an integer (a bool is not accepted), score_by is not a list of clauses (wrap a single clause as [clause]), holds an item that is neither a dict nor one of the six clause types (such as a SearchQuery), filter is not a dict (call .to_dict() on a filter-builder Condition), or include_fields is a bare str rather than a list.

Return type:

SearchDocumentsResponse

Examples

from pinecone import TextQuery

response = await idx.documents.search(
    namespace="published",
    top_k=5,
    score_by=[TextQuery(query="machine learning", fields=["content"])],
    include_fields=["title", "content"],
    filter={"category": {"$eq": "tech"}},
)
for doc in response.matches:
    print(doc.id, doc.score)

Filter on a schema field with a text-match operator (here title is a string field declared with full_text_search):

response = await idx.documents.search(
    namespace="published",
    top_k=5,
    score_by=[TextQuery(query="machine learning", fields=["content"])],
    filter={"title": {"$match_phrase": "machine learning"}},
)

See also

  • search(): record search for legacy integrated indexes, through the legacy Records API.

  • query(): nearest-neighbor search over vectors you provide.

async fetch(*, namespace, ids=None, filter=None, include_fields=None, pagination_token=None, limit=None, timeout=None)[source]

Fetch documents from a namespace by ID or by metadata filter.

Exactly one of ids or filter must be provided. A filtered fetch returns matching documents a page at a time, with response.pagination carrying the token for the next page.

Parameters:
  • namespace (str) – Namespace to fetch from (required, non-empty).

  • ids (Sequence[str] | None) – Document IDs to fetch. IDs that do not exist are omitted from the result rather than raising. Mutually exclusive with filter.

  • filter (Mapping[str, Any] | None) –

    Non-empty filter expression selecting the documents to fetch. Mutually exclusive with ids. Which operators a predicate may use depends on the field it names:

    • A data field, one the schema declares to be searched (a vector field, or a string declared with full_text_search, embed or sparse_embed), rejects comparison operators such as $eq with a 400. Of these, a string whose text is stored and searchable takes the text-match operators: one declared with full_text_search, or with embed or sparse_embed and the default store_text (the server turns full-text search on for it). A store_text=False string does not, and neither does a vector field. The operators are $match_phrase (the words as a contiguous, ordered phrase), $match_all (every word, in any order) and $match_any (at least one word).

    • A metadata field, one the schema does not declare or declares only for filtering (an integer, float, boolean, string list, or a string with no search configuration), takes the comparison, set and logical operators ($eq, $in, $gte and so on). A text-match operator on it is rejected with a 400.

    The two kinds combine under $and.

  • include_fields (Sequence[str] | None) – Document fields to include in each document. Omitting it (the default), [], or ["*"] each return every field; a list of names returns just those. search() is the opposite: there, omitting the argument returns only _id and _score. Every field means every field the index stores: a field declared with store_text: false is left out, and naming one is rejected by the server with a 400.

  • pagination_token (str | None) – Token from a previous filtered fetch response to retrieve the next page. Only valid together with filter.

  • limit (int | None) – Maximum number of documents per page of a filtered fetch. Omitting it uses the server’s default page size. A fetch by ids ignores it.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only. Must be greater than zero.

Returns:

FetchDocumentsResponse with documents (document ID mapped to a Document, reached as doc.<field>), namespace, usage, and pagination, which carries the next-page token when a filtered fetch has more results and is None otherwise.

Raises:
  • PineconeValueError – If namespace is empty, both or neither of ids and filter are provided, filter is an empty dict, ids holds more IDs than one request accepts, pagination_token is passed without filter, or limit is outside its accepted range. Also raised if timeout is zero or negative.

  • PineconeTypeError – If limit is not an integer (a bool is not accepted), filter is not a dict (call .to_dict() on a filter-builder Condition), or ids or include_fields is a bare str rather than a list.

Return type:

FetchDocumentsResponse

Examples

Fetch specific documents by ID. IDs that do not exist are absent from response.documents rather than raising:

response = await idx.documents.fetch(
    namespace="published",
    ids=["article-101", "article-102"],
)
for doc_id, doc in response.documents.items():
    print(doc_id, doc.title)

Fetch by filter instead. A filtered fetch is paginated, so read each page’s documents before asking for the next one; the loop below is the whole retrieval, not just the token bookkeeping:

pagination_token = None
while True:
    response = await idx.documents.fetch(
        namespace="published",
        filter={"category": {"$eq": "tech"}},
        pagination_token=pagination_token,
    )
    for doc_id, doc in response.documents.items():
        print(doc_id, doc.title)
    if response.pagination is None:
        break
    pagination_token = response.pagination.next

A filter can use a text-match operator on a schema field, here title, a string field declared with full_text_search, instead of a comparison on a metadata field:

response = await idx.documents.fetch(
    namespace="published",
    filter={"title": {"$match_any": "vectors retrieval"}},
)

See also

  • search(): when you want the best-matching documents rather than every document that satisfies a filter.

  • fetch(): for indexes where you provide your own vectors.

  • Pagination: the pagination shapes the SDK uses and when each applies.

async delete(*, namespace, ids=None, filter=None, delete_all=False, timeout=None)[source]

Delete documents from a namespace by ID, filter, or delete-all flag.

Exactly one of ids, filter, or delete_all must be provided. Deleting IDs that do not exist does not raise an error.

Pinecone applies the delete asynchronously. For a filtered delete, response.matched_records is the point-in-time count of matching documents when the delete was accepted, not a guarantee of the number ultimately deleted.

Parameters:
  • namespace (str) – Namespace to delete from (required, non-empty).

  • ids (Sequence[str] | None) – Document IDs to delete. Mutually exclusive with filter and delete_all.

  • filter (Mapping[str, Any] | None) – Non-empty metadata filter expression selecting the documents to delete. Text-match operators ($match_phrase, $match_all, $match_any) are not supported here. Mutually exclusive with ids and delete_all. Pass a dict; for a filter-builder Condition, pass condition.to_dict().

  • delete_all (bool) – If True, delete all documents in the namespace. Mutually exclusive with ids and filter.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only. Must be greater than zero.

Returns:

DeleteDocumentsResponse. matched_records is populated only for filtered deletes (None for by-ID and delete-all paths, and when the count could not be read in time).

Raises:
  • PineconeValueError – If namespace is empty, zero or more than one of ids/filter/delete_all is provided, filter is an empty dict, or ids holds more IDs than one request accepts. Also raised if timeout is zero or negative.

  • PineconeTypeError – If filter is not a dict (call .to_dict() on a filter-builder Condition), or ids is a bare str rather than a list.

Return type:

DeleteDocumentsResponse

Examples

Delete specific documents by ID:

await idx.documents.delete(namespace="published", ids=["article-101"])

Delete every document matching a filter:

response = await idx.documents.delete(
    namespace="published",
    filter={"category": {"$eq": "obsolete"}},
)
print(response.matched_records)

Or empty a namespace outright. delete_all removes every document in the namespace named; it takes no ids or filter to narrow it:

await idx.documents.delete(namespace="drafts", delete_all=True)

See also

  • delete_namespace(): to remove the namespace itself, rather than emptying it with delete_all.

  • delete(): for indexes where you provide your own vectors.

async update(*, namespace, documents=None, filter=None, set_fields=None, remove_fields=None, timeout=None)[source]

Apply partial updates to documents in a namespace.

Documents are selected either per ID with documents, or in bulk with filter plus set_fields and/or remove_fields. The two shapes are mutually exclusive. Fields that are not mentioned are left unchanged, and an update naming a document that does not exist is accepted as a no-op rather than raising.

Pinecone applies the update asynchronously. For a filtered update, response.matched_records is the point-in-time count of matching documents when the update was accepted, not a guarantee of the number ultimately patched.

Parameters:
  • namespace (str) – Namespace to update in (required, non-empty).

  • documents (Sequence[Mapping[str, Any] | UpdateDocumentRecord] | None) – Per-document patches. Each element is a dict with an _id key or an UpdateDocumentRecord. Any key other than _id and _remove_fields sets a new value for that field; the names in _remove_fields are removed from the document. _id values must be unique within the request. Mutually exclusive with filter, set_fields, and remove_fields.

  • filter (Mapping[str, Any] | None) – Non-empty metadata filter expression selecting the documents to patch. Text-match operators ($match_phrase, $match_all, $match_any) are not supported here. Mutually exclusive with documents. Pass a dict; for a filter-builder Condition, pass condition.to_dict().

  • set_fields (Mapping[str, Any] | None) – Fields to set on every document matching filter, and the values to set them to. Only valid with filter.

  • remove_fields (Sequence[str] | None) – Names of the fields to remove from every document matching filter. Only valid with filter.

  • timeout (float | None) – Per-request timeout in seconds. Overrides the client-level default for this call only. Must be greater than zero.

Returns:

UpdateDocumentsResponse. matched_records is populated only for filtered updates (None for per-ID updates, and when the count could not be read in time). usage.embed_total_tokens counts the tokens Pinecone embedded for embed and sparse_embed fields; usage is None when the update embedded no text.

Raises:
  • PineconeValueError – If namespace is empty, documents is combined with any by-filter field, neither documents nor filter is given, set_fields or remove_fields is passed without filter, filter is an empty dict or carries no patch, documents is empty or longer than one request accepts, or a patch is malformed; the message names the offending position. Also raised if timeout is zero or negative.

  • ApiError – If a field value is None, which the server rejects; use _remove_fields (per-ID) or remove_fields (by-filter) to remove a field instead.

  • PineconeTypeError – If filter is not a dict (call .to_dict() on a filter-builder Condition), or remove_fields is a bare str rather than a list.

Return type:

UpdateDocumentsResponse

Examples

Patch documents by ID. Each key other than the reserved _id and _remove_fields sets that field’s value; fields the patch does not name keep the values they already have, so article-101 here gets a new title and is otherwise untouched:

await idx.documents.update(
    namespace="published",
    documents=[
        {"_id": "article-101", "title": "An introduction to vector search"},
        {"_id": "article-102", "_remove_fields": ["draft_notes"]},
    ],
)

article-102 keeps every field it has except draft_notes: _remove_fields names fields to delete rather than setting a field called _remove_fields.

Patch every document matching a filter instead, setting one field and removing another across all of them:

response = await idx.documents.update(
    namespace="published",
    filter={"category": {"$eq": "news"}},
    set_fields={"review_status": "archived"},
    remove_fields=["draft_notes"],
)
print(response.matched_records)

See also

  • upsert(): to replace a document outright; an upsert of an existing _id drops the fields it does not mention, where this method keeps them.

  • update(): for indexes where you provide your own vectors.

list(*, namespace, prefix=None, limit=None, pagination_token=None, timeout=None)[source]

List the documents in a namespace, following pagination lazily.

Returns an AsyncPaginator that fetches pages on demand and stops when the server returns no pagination token. Documents come back in sorted order by ID, carrying only their _id.

Parameters:
  • namespace (str) – Namespace to list from (required, non-empty).

  • prefix (str | None) – Return only documents whose IDs begin with this prefix, such as "article-". Must be ASCII. None lists every document.

  • limit (int | None) – Maximum number of documents the server returns per page. This tunes the page size, not the total: the paginator follows every page. None (default) lets the server choose the page size. To stop early, break out of the loop.

  • pagination_token (str | None) – Token from a previous list response to resume from, rather than starting at the first page.

  • timeout (float | None) – Per-request timeout in seconds, applied to each page request. Overrides the client-level default. Must be greater than zero.

Returns:

AsyncPaginator over ListedDocumentRecord objects. Supports async for, to_list(), and pages().

Raises:
  • PineconeTypeError – If limit is not an integer (a bool is not accepted).

  • PineconeValueError – If namespace is empty, prefix is too long or not ASCII, or limit is outside its accepted range. Raised by this call, before the paginator is returned. Also raised if timeout is zero or negative.

Return type:

AsyncPaginator[ListedDocumentRecord]

Examples

Iterate every document ID in the namespace, letting the paginator cross page boundaries for you:

async for doc in idx.documents.list(namespace="published", prefix="article-1"):
    print(doc.id)

Or take the pages themselves, when you want to checkpoint a long walk on the token each page carries:

paginator = idx.documents.list(namespace="published", limit=20)
async for page in paginator.pages():
    print(len(page.items), page.pagination_token)

See also

  • fetch(): to read the fields of the documents, not just their IDs.

  • list(): for indexes where you provide your own vectors.

  • Pagination: the pagination shapes the SDK uses and when each applies.