Notice
This document is for a development version of Ceph.
S3 Vectors
Added in version Vampire.
S3 Vectors provide a mechanism for storing, indexing, and querying high-dimension vectors (embeddings) inside the RGW. Vectors are grouped into indexes, and indexes are grouped into vector buckets. Each vector has a key, the vector data itself, and an optional JSON metadata document that can be used to filter query results.
The API implemented by the RGW follows the AWS S3 Vectors API. Applications that already use the AWS SDK for S3 Vectors should be able to work in the same way by pointing the SDK at the RGW. A small number of extensions to the AWS API are provided, and are marked as such throughout this document.
Requests are sent as POST requests with a JSON body, and are signed using
AWS Signature Version 4 with the s3vectors service name.
Note
To enable the S3 Vectors API, the rgw_enable_apis
configuration parameter should contain: “s3vectors”.
Storage Backends
The vector data and the indexes built on top of it are stored by an embedded LanceDB engine. The location in which LanceDB stores its files is selected with:
- rgw_s3vector_backend
Specifies the storage backend for S3 Vector (LanceDB). Use “local” for local filesystem storage, or “rgw” for RGW’s internal Storage Abstraction Layer (same Ceph cluster).
- type:
str- runtime updatable:
true- default:
rgw- valid choices:
localrgw
Two backends are supported:
rgw(the default): LanceDB files are stored in the same Ceph cluster, through the RGW storage abstraction layer. No external service and no extra configuration are needed.local: LanceDB files are stored on the local filesystem of the RGW process. This backend is intended for testing and single RGW setups only: vector buckets created on one RGW will not be usable from another one.
The local backend is configured with:
- rgw_s3vector_local_path
The local filesystem path where LanceDB databases will be stored when using the “local” backend. Each vector bucket will be created as a subdirectory.
- type:
str- runtime updatable:
true- default:
/var/lib/ceph/radosgw/$cluster-$id/s3vector-lancedb
Note
The files are written by the RGW process, as the user it runs as
so the path must be writable by that user. Purging the data of a user
or an account with radosgw-admin removes the files as well,
and the command therefore has to run on the RGW host, as a user with
write access to the path.
Backing Buckets
With the rgw backend, LanceDB stores its files inside a regular S3 bucket.
The name of that bucket is identical to the name of the vector bucket.
This bucket is not created automatically: it must be created before
CreateVectorBucket is called.
For example, to create a vector bucket named my-vectors, first create a
regular S3 bucket named my-vectors at the RGW endpoint, and only then call
CreateVectorBucket.
Note
S3 buckets are kept in separate namespaces, and a name may be used by both at the same time. Listing S3 buckets does not show vector buckets, and listing vector buckets does not show S3 buckets.
Ownership
Since the credentials used for the S3 bucket are the same as the credentials used in the S3 vectors request, it is advised that the same user will be owner of both. If not, proper policy must be set to allow the user to access the S3 bucket.
Because the backing bucket holds the raw vector data, anyone who is granted plain S3 access to it can read, modify or delete vectors and indexes without passing through the S3 Vectors API and its permission checks. Write access to the backing bucket should therefore be restricted to its owner, or to the users performing the vector bucket operations.
Recommended Bucket Configuration
The following is recommended for any bucket that backs a vector bucket:
Disable sync on the bucket. In a multisite configuration, each zone maintains its own copy of the vector data (see Multisite below).
radosgw-admin bucket sync disable --bucket={bucket-name}Alternatively, use a bucket-level sync policy that does not enable any pipe for this bucket. See: Multisite Sync Policy.
Do not enable object locking. LanceDB continuously rewrites and removes files as vectors are added, deleted and compacted, which does not go well with a retention period.
Do not enable versioning. LanceDB does not support versioned objects, and object deletions would leave behind stale files that are not cleaned up.
Multisite
In a multisite configuration, S3 Vectors entities are not synced between the zones of a zonegroup. Neither the metadata of the vector buckets and their indexes, nor the vector data itself, is synced.
Each zone has its own vector buckets, and a vector bucket has to be created in every zone in which it is needed. A vector bucket of the same name may exist in more than one zone, holding different indexes and vectors.
The backing bucket of a vector bucket is a regular S3 bucket, and its own sync configuration applies to it. It should not be synced. See: Recommended Bucket Configuration.
Metadata Filtering
Every vector may carry a JSON metadata document. QueryVectors accepts a
filter expression over that metadata, so that only the vectors matching the
filter participate in the result. See: AWS metadata filtering.
Filter Syntax
The filter is a JSON object following the syntax used by AWS metadata
filtering. It is evaluated against the metadata document of each vector, and
only the vectors for which it evaluates to true take part in the result. An
empty filter
({}) matches every vector.
A filter that cannot be evaluated is rejected before the query runs, with a
ValidationException whose fieldList points at filter. See:
S3 Vectors REST API.
The examples below assume vectors carrying metadata of this shape:
{"genre": "rock", "year": 2021, "active": true, "tags": ["live", "remaster"]}
Field Conditions
A filter object maps metadata field names to conditions. A condition is either a bare value, which means equality, or an object of operators:
{"genre": "rock"} // genre == "rock"
{"genre": {"$eq": "rock"}} // the same condition, written explicitly
{"year": {"$gte": 2000, "$lt": 2026}} // 2000 <= year < 2026
Multiple operators on the same field are combined with a logical AND, and so are multiple fields at the top level of the filter:
{"genre": "rock", "year": {"$gte": 2000}} // genre == "rock" AND year >= 2000
Field names always refer to top-level keys of the metadata document. Nested documents cannot be addressed, and a name that is not a valid metadata key name is rejected with a validation error, since no such key could have been stored. See: Metadata Key Names.
A field that was declared in nonFilterableMetadataKeys must not appear in a filter at all.
A field that was declared in filterableMetadataKeys would be used in pre-filtering.
A field which appeared in neither of these list would be used in post-filtering.
See: Pre-Filtering and Post-Filtering.
Comparison Operators
$eq,$ne: equal, not equal.$gt,$gte,$lt,$lte: greater than, greater or equal, less than, less or equal. Numbers are compared numerically, strings lexicographically.
Each of them takes a single string, number or boolean value:
{"genre": {"$ne": "blues"}}
{"active": {"$eq": true}}
{"year": {"$gt": 2019, "$lt": 2026}}
The value may not be null, an array, or an object. These are all rejected:
{"genre": null} // null is not a value
{"genre": {"$ne": null}} // also as an operand
{"tags": ["live"]} // implicit equality with an array
{"tags": {"$eq": ["live"]}} // arrays are not comparable
{"genre": {"$eq": {"a": "b"}}} // objects are not comparable
{"genre": {"$regex": "ro.*"}} // unknown operator
$in and $nin
$in matches when the field is equal to one of the values in the list, and
$nin when it is equal to none of them. Both take a non-empty JSON array of
scalar values:
{"genre": {"$in": ["rock", "jazz"]}}
{"year": {"$nin": [2020, 2021]}}
{"genre": {"$in": ["rock"]}} // a single-element list is fine
The array must hold scalars only, and it must not be empty. For a field that is not filterable, all the elements must also be of the same JSON type, since the type of the elements determines how the metadata field is read. These are rejected:
{"genre": {"$in": []}} // empty list
{"genre": {"$in": "rock"}} // not a list
{"genre": {"$in": {"a": "b"}}} // not a list
{"genre": {"$in": ["rock", 42]}} // mixed types
{"genre": {"$in": [null, "rock"]}} // null element
{"genre": {"$in": [{"a": "b"}]}} // object element
For a filterable field, each element is converted to the declared type of the
field instead, so a list such as ["rock", 42] is accepted on a String
field and read as ["rock", "42"].
Note that $in tests the value of the field, not membership in a stored
list. See Lists in the Metadata below.
$exists
$exists tests whether the field is present, and takes an unquoted true
or false:
{"tags": {"$exists": true}} // the vector has a "tags" field
{"tags": {"$exists": false}} // the vector has no "tags" field
Anything else is rejected, including a quoted boolean:
{"tags": {"$exists": "true"}}
{"tags": {"$exists": 1}}
For a field stored in the metadata document, $exists only checks that the
key is there; its value may be of any type, including an array or a nested
object. A vector that was stored without any metadata has no keys at all, so
$exists: false matches it. For a filterable field, that was declared with
mustExist the key is always there, so $exists: true matches every
vector of the index and $exists: false matches none.
Logical Operators
$and and $or take a non-empty array of filter objects, and may be
nested to any depth:
{"$and": [{"genre": "rock"}, {"year": {"$gte": 2000}}]}
{"$or": [{"genre": "rock"}, {"genre": "jazz"}]}
{
"$and": [
{"$or": [{"genre": "rock"}, {"genre": "jazz"}]},
{"year": {"$gte": 2000, "$lte": 2025}},
{"active": true}
]
}
The array must be non-empty, and each of its elements must be a filter object:
{"$and": []} // empty array
{"$or": {"genre": "rock"}} // not an array
{"$or": [1, 2, 3]} // elements are not filter objects
There is no $not operator. A negation is expressed with $ne, $nin
or $exists: false.
$or has an additional restriction when some of the fields are filterable.
See: Post-Filtering Limitations.
Value Types
For a field that is stored in the metadata document, the JSON type of the value
in the filter selects how the field is read: a quoted value is read as a
string, true/false as a boolean, and anything else as a number.
A condition therefore only matches when the types agree:
{"year": 2021} // matches metadata {"year": 2021}
{"year": "2021"} // does not match it: "year" is read as a string
{"genre": {"$eq": 42}} // does not match it: "genre" is read as a number
{"active": {"$eq": "true"}} // does not match it: "active" is read as a string
For a field that is declared as a filterable field, the declared type of the field wins, and the value from the filter is converted to it. Quoting does not matter, and a value that cannot be converted is rejected:
{"year": {"$eq": "2021"}} // Number field: accepted, converted to 2021
{"genre": {"$eq": 42}} // String field: accepted, converted to "42"
{"active": {"$eq": "true"}} // Boolean field: accepted, converted to true
{"year": {"$eq": "recent"}} // Number field: rejected
{"active": {"$eq": "yes"}} // Boolean field: rejected
Lists in the Metadata
A metadata field whose value is a list, such as "tags" above, can only be
tested with $exists. There is no operator for testing the members of a
stored list: the comparison operators, $in and $nin all compare the
value of the field against the value in the filter, and a list value never
compares equal to a scalar. So with the metadata above:
{"tags": {"$exists": true}} // matches
{"tags": "live"} // does not match
{"tags": {"$in": ["live"]}} // does not match
This holds for filterable fields as well, and there it is an error rather than
a non-match: a key declared with one of the list types (StringList,
NumberList, BooleanList) supports $exists only, and any other
operator on it is rejected with a validation error.
Note
This is a divergence from the AWS S3 Vectors API. Array membership is not supported here, and such a filter does not match. See: AWS metadata filtering.
Missing Fields
A condition on a field that the vector does not have never matches. This
includes the negative operators: a vector without a genre field is not
matched by {"genre": {"$ne": "rock"}} or by
{"genre": {"$nin": ["rock"]}}. To include those vectors, combine the
condition with $exists:
{"$or": [{"genre": {"$ne": "rock"}}, {"genre": {"$exists": false}}]}
The same applies to a filterable field that was not declared with
mustExist.
Pre-Filtering and Post-Filtering
By default, metadata is stored as a JSON document next to the vector, and is
not part of the index schema. A filter over such a field can only be evaluated
after the vector search has returned its candidates. This is called
post-filtering: the index is asked for topK nearest vectors, and the
filter is then applied to that result set. Vectors that do not match are
dropped, so the query may return fewer than topK results even when enough
matching vectors exist in the index.
To avoid that, an index may declare some metadata fields as filterable. A
filterable field is stored as a real field of the index, and a filter over it
is pushed down into the vector search itself. This is called pre-filtering:
only matching vectors are considered by the search, so a query returns topK
results whenever the index holds at least topK matching vectors.
Filterable fields are declared at index creation time, using the
filterableMetadataKeys field of metadataConfiguration. This is an
extension to the AWS S3 Vectors API. See: Create Index.
Note
The AWS API has a nonFilterableMetadataKeys list, which is also
supported. It marks fields that may never be used in a filter: a filter that
references such a field is rejected with a validation error.
A single filter may mix filterable fields and plain JSON metadata fields. In that case the conditions on the filterable fields are pushed down into the search, and the conditions on the JSON fields are applied to the search result.
Post-Filtering Limitations
Since post-filtering discards vectors that were already returned by the search,
some oversampling is needed to have a reasonable chance of returning topK
results. Whenever any part of the filter must be post-filtered, the number of
candidates fetched from the index is topK multiplied by:
- rgw_s3vector_topk_post_filter_factor
When a vector query uses metadata filtering on non-column fields, multiply topK by this factor to fetch more candidates from the index before post-filtering. Higher values increase the chance of returning the full topK results after filtering, at the cost of more work.
- type:
float- runtime updatable:
true- default:
1.0- allowed range:
[1, 10]
With the default value of 1 no oversampling is done. Raising it increases
the chance of returning a full result set at the cost of reading and filtering
more candidates. Note that even with a high factor, returning topK results
is never guaranteed, since the matching vectors may all be far away from the
query vector.
The $or operator has an additional limitation: its branches must be either
all filterable fields or all JSON metadata fields. A $or that mixes the
two cannot be evaluated correctly, because one half of the expression would be
applied before the search and the other half after it, and the request is
rejected with a validation error. To run such a query, set postFiltering to
true in the QueryVectors request. This is an extension to the AWS S3
Vectors API, which forces the whole filter to be evaluated as post-filtering:
declared filterable fields are ignored, and every condition is evaluated
against the JSON metadata document.
S3 Vectors REST API
Note
In all S3 Vectors actions, the operation name is the path of the request,
the parameters are sent in the message body using this content type:
application/json, and the response body is JSON as well:
POST /<ActionName> HTTP/1.1
Content-Type: application/json
{<request parameters>}
Vector buckets and indexes may be identified either by name or by ARN. Both may not be given in the same request. The ARN formats are:
arn:aws:s3vectors:<zone-group>:<account>:bucket/<vector-bucket>
arn:aws:s3vectors:<zone-group>:<account>:bucket/<vector-bucket>/index/<index>
In case that CreateIndex, PutVectors and QueryVectors,
encounter errors that are the result of an invalid request, they return a 400
status, the ValidationException code, and a fieldList array that points
at the offending fields:
{
"code": "ValidationException",
"message": "The requested action isn't valid.",
"fieldList": [
{
"path": "vectors[0].data",
"message": "expected dimension 4 but got 3"
}
]
}
Other requests that encounter errors that are the result of an invalid request return a 400 status and
the InvalidArgument code, without a fieldList.
Metadata Key Names
The same rules apply to every metadata key name: the ones declared at
CreateIndex, the top-level field names of the metadata document of a
vector, and the field names used in a query filter. A key name:
must not be empty
must not start with an underscore (
_), since names with that prefix are reserved for internal fields of the index. (This is an extension to the S3 Vectors API, which accepts such names.)must not contain a
.so they are not confused with nested fields. (A metadata value may be a nested object, unlike in the S3 Vectors API, which is why a dotted name is reserved. See: Put Vectors.)
A name that breaks any of these rules is rejected with a validation error.
Note
No other character is reserved. A name may hold spaces, quotes, backticks and
non-ASCII characters, may begin with a digit, and may be the name of a filter
operator, such as $eq or $or.
Note
Key names are case sensitive: Genre and genre are two different keys,
and may both be stored on the same vector.
Vector Buckets
Create Vector Bucket
Creates a new vector bucket. The bucket name must be between 3 and 63
characters long. With the rgw backend, a regular S3 bucket with the same
name must already exist. See: Backing Buckets.
POST /CreateVectorBucket
{
"vectorBucketName": "<vector-bucket>"
}
The response has the following format:
{
"vectorBucketArn": "arn:aws:s3vectors:::bucket/<vector-bucket>"
}
Get Vector Bucket
Returns information about a specific vector bucket.
POST /GetVectorBucket
{
"vectorBucketName": "<vector-bucket>" | "vectorBucketArn": "<vector-bucket-arn>"
}
The response has the following format:
{
"vectorBucket": {
"creationTime": "<iso-8601-timestamp>",
"vectorBucketArn": "<vector-bucket-arn>",
"vectorBucketName": "<vector-bucket>"
}
}
List Vector Buckets
Lists the vector buckets owned by the requesting user.
POST /ListVectorBuckets
{
["maxResults": <number>,]
["nextToken": "<token>",]
["prefix": "<prefix>"]
}
Request parameters:
maxResults: The maximum number of buckets to return. Must be between 1 and 500. (This is 500 by default.)nextToken: The pagination token returned by a previous call.prefix: Return only buckets whose name starts with this prefix. Must be between 1 and 63 characters long.
The response has the following format:
{
"nextToken": "<token>",
"vectorBuckets": [
{
"creationTime": "<iso-8601-timestamp>",
"vectorBucketArn": "<vector-bucket-arn>",
"vectorBucketName": "<vector-bucket>"
}
]
}
nextToken is present only if more buckets exist beyond the returned page.
Delete Vector Bucket
Deletes a vector bucket. All of the indexes of the vector bucket must be deleted before the vector bucket itself can be deleted.
POST /DeleteVectorBucket
{
"vectorBucketName": "<vector-bucket>" | "vectorBucketArn": "<vector-bucket-arn>"
}
Note
A vector bucket that still holds indexes is not deleted. The request
fails with a 409 status and the BucketNotEmpty code, and neither the
bucket nor its indexes are modified. Use Delete Index on each of the
indexes of the bucket, and then delete the bucket.
Note
The backing S3 bucket itself is not deleted, and should be removed separately if it is no longer needed.
Vector Bucket Policy
The PutVectorBucketPolicy, GetVectorBucketPolicy and
DeleteVectorBucketPolicy actions exist, and validate that the vector bucket
exists, but the policy itself is not yet stored or enforced.
POST /PutVectorBucketPolicy
{
"policy": "<policy-JSON-string>",
"vectorBucketName": "<vector-bucket>" | "vectorBucketArn": "<vector-bucket-arn>"
}
POST /GetVectorBucketPolicy
{
"vectorBucketName": "<vector-bucket>" | "vectorBucketArn": "<vector-bucket-arn>"
}
POST /DeleteVectorBucketPolicy
{
"vectorBucketName": "<vector-bucket>" | "vectorBucketArn": "<vector-bucket-arn>"
}
Indexes
Create Index
Creates a new index inside a vector bucket. The index name must be between 3 and 63 characters long.
POST /CreateIndex
{
"dataType": "float32",
"dimension": <number>,
"distanceMetric": "cosine" | "euclidean",
"indexName": "<index>",
["metadataConfiguration": {
["nonFilterableMetadataKeys": ["<key>"],]
["filterableMetadataKeys": [
{
"name": "<key>",
["type": "String" | "Number" | "Boolean" | "StringList" | "NumberList" | "BooleanList",]
["mustExist": true|false]
}
]]
},]
"vectorBucketName": "<vector-bucket>" | "vectorBucketArn": "<vector-bucket-arn>"
}
Request parameters:
dataType: The type of the vector elements. Onlyfloat32is supported.dimension: The number of elements in each vector. Must be between 1 and 4096. All vectors written to the index must have exactly this dimension.distanceMetric: The metric used to compare vectors, eithercosineoreuclidean.metadataConfiguration.nonFilterableMetadataKeys: Up to 10 metadata keys that may not be used in a query filter. A filter that references one of them is rejected. Key names must be valid (see: Metadata Key Names) and must not be repeated in the list. Each key must not exceed 63 characters, and must not contain a backtick (this restriction does not exist with AWS S3 Vectors API).metadataConfiguration.filterableMetadataKeys: Up to 10 metadata keys that are stored as fields of the index, so that filters over them are evaluated before the vector search. (This is an extension to the S3 Vectors API. See: Metadata Filtering.) Each entry has:name: The metadata key. Must be a valid key name (see: Metadata Key Names), must not exceed 63 characters, and must not contain a backtick. A key must not be repeated in the list, even with a differenttypeormustExist, and may not appear both infilterableMetadataKeysand innonFilterableMetadataKeys.type: The type of the value. (This isStringby default.) The list types may be stored and returned but cannot be used in a filter.mustExist: If “true”, every vector written to the index must have this key in its metadata, and aPutVectorsrequest that omits it fails with a validation error. (This is “false” by default.)
The response has the following format:
{
"indexArn": "<index-arn>"
}
Get Index
Returns the configuration of a specific index.
POST /GetIndex
{
"indexName": "<index>",
"vectorBucketName": "<vector-bucket>" | "indexArn": "<index-arn>"
}
The response has the following format:
{
"index": {
"creationTime": <number>,
"dataType": "float32",
"dimension": <number>,
"distanceMetric": "cosine" | "euclidean",
"indexArn": "<index-arn>",
"indexName": "<index>",
"metadataConfiguration": {
"nonFilterableMetadataKeys": ["<key>"],
"filterableMetadataKeys": [
{"name": "<key>", "type": "<type>", "mustExist": true|false}
]
},
"vectorBucketName": "<vector-bucket>"
}
}
List Indexes
Lists the indexes of a vector bucket.
POST /ListIndexes
{
["maxResults": <number>,]
["nextToken": "<token>",]
["prefix": "<prefix>",]
"vectorBucketName": "<vector-bucket>" | "vectorBucketArn": "<vector-bucket-arn>"
}
Request parameters:
maxResults: The maximum number of indexes to return. Must be between 1 and 500. (This is 500 by default.)nextToken: The pagination token returned by a previous call.prefix: Return only indexes whose name starts with this prefix. Must be between 1 and 63 characters long.
The response has the following format:
{
"indexes": [
{
"creationTime": <number>,
"indexArn": "<index-arn>",
"indexName": "<index>",
"vectorBucketName": "<vector-bucket>"
}
],
"nextToken": "<token>"
}
nextToken is present only if more indexes exist beyond the returned page.
Note
When prefix is used, the indexes are filtered after they are
listed, so a page may hold fewer than maxResults indexes, or none at all,
while more matching indexes still exist. Pagination should continue until a
response holds no nextToken.
Delete Index
Deletes an index and all of the vectors it holds.
POST /DeleteIndex
{
"indexName": "<index>",
"vectorBucketName": "<vector-bucket>" | "indexArn": "<index-arn>"
}
Note
An index that still holds vectors may be deleted. Its vectors are removed together with it, and there is no need to delete them first.
Note
Deleting an index that does not exist is not considered an error, and
returns a 200 status.
Vectors
Put Vectors
Adds vectors to an index, or overwrites vectors that already exist under the same keys.
POST /PutVectors
{
"indexName": "<index>",
"vectorBucketName": "<vector-bucket>" | "indexArn": "<index-arn>",
"vectors": [
{
"key": "<key>",
"data": {"float32": [<float>]},
["metadata": {<JSON object>}]
}
]
}
Request parameters:
vectors: Between 1 and 500 vectors. Each has:key: The identifier of the vector inside the index. Must be between 1 and 1024 characters long.data.float32: The vector itself. Its length must match thedimensionof the index.metadata: An optional JSON object attached to the vector. It may hold up to 50 top-level fields, and must not exceed 40KB. Field names must be valid (see: Metadata Key Names) and must not be duplicated, and a field must not hold anullvalue. A value may be an object, so the document may be nested. This is an extension to the S3 Vectors API, which only accepts strings, numbers, booleans and arrays as metadata values, and rejects a nested object. The rules above are validated for the top-level fields of the document only: a nested document may hold duplicate names, names with a., andnullvalues, but its fields cannot be used in a filter. (See: Filter Syntax.) Any field that was declared infilterableMetadataKeysmust hold a value of the declared type, and must be present if the key was declared withmustExist.
An empty response body is returned on success.
Get Vectors
Returns specific vectors by key.
POST /GetVectors
{
"indexName": "<index>",
"vectorBucketName": "<vector-bucket>" | "indexArn": "<index-arn>",
"keys": ["<key>"],
["returnData": true|false,]
["returnMetadata": true|false]
}
Request parameters:
keys: Between 1 and 100 keys. Each key must be between 1 and 1024 characters long.returnData: If “true”, the vector data is returned. (This is “false” by default.)returnMetadata: If “true”, the vector metadata is returned. (This is “false” by default.)
The response has the following format:
{
"vectors": [
{
"key": "<key>",
"data": {"float32": [<float>]},
"metadata": {<JSON object>}
}
]
}
Note
Keys that do not exist in the index are silently omitted from the response.
List Vectors
Lists the vectors of an index.
POST /ListVectors
{
"indexName": "<index>",
"vectorBucketName": "<vector-bucket>" | "indexArn": "<index-arn>",
["maxResults": <number>,]
["nextToken": "<token>",]
["returnData": true|false,]
["returnMetadata": true|false,]
["segmentCount": <number>,]
["segmentIndex": <number>]
}
Request parameters:
maxResults: The maximum number of vectors to return. Must be between 1 and 1000. (This is 500 by default.)nextToken: The pagination token returned by a previous call. Note that in our implementation the token is a numeric offset and not an opaque string.returnData: If “true”, the vector data is returned. (This is “false” by default.)returnMetadata: If “true”, the vector metadata is returned. (This is “false” by default.)
Note
Segmented listing is not implemented. Only a single segment may be
requested: segmentCount must be 1 and segmentIndex must be 0, which
lists the entire index.
The response has the following format:
{
"nextToken": "<token>",
"vectors": [
{
"key": "<key>",
"data": {"float32": [<float>]},
"metadata": {<JSON object>}
}
]
}
Note
The order in which vectors are listed is not defined, and vectors that are added or removed while a listing is in progress may or may not be returned.
Query Vectors
Returns the vectors of an index that are nearest to a given query vector,
according to the distanceMetric of the index.
POST /QueryVectors
{
"indexName": "<index>",
"vectorBucketName": "<vector-bucket>" | "indexArn": "<index-arn>",
"queryVector": {"float32": [<float>]},
"topK": <number>,
["filter": {<filter expression>},]
["returnDistance": true|false,]
["returnMetadata": true|false,]
["postFiltering": true|false]
}
Request parameters:
queryVector.float32: The vector to search for. Its length must match thedimensionof the index.topK: The maximum number of vectors to return. Must be between 1 and 10000.filter: A filter over the vector metadata. See: Metadata Filtering.returnDistance: If “true”, the distance from the query vector is returned for each result. (This is “false” by default.)returnMetadata: If “true”, the vector metadata is returned. (This is “false” by default.)postFiltering: If “true”, the whole filter is evaluated against the JSON metadata after the search, and filterable fields are ignored. (This is “false” by default, and is an extension to the S3 Vectors API. See: Post-Filtering Limitations.)
The response has the following format:
{
"distanceMetric": "cosine" | "euclidean",
"vectors": [
{
"distance": <float>,
"key": "<key>",
"metadata": {<JSON object>}
}
]
}
Results are ordered by their distance from the query vector, nearest first.
Delete Vectors
Deletes specific vectors from an index by key.
POST /DeleteVectors
{
"indexName": "<index>",
"vectorBucketName": "<vector-bucket>" | "indexArn": "<index-arn>",
"keys": ["<key>"]
}
Request parameters:
keys: Between 1 and 500 keys. Each key must be between 1 and 1024 characters long.
Note
Deleting a key that does not exist in the index is not considered an error.
Permissions
Access to the S3 Vectors actions is controlled by identity-based policies, using the following actions:
s3vectors:CreateVectorBuckets3vectors:GetVectorBuckets3vectors:ListVectorBucketss3vectors:DeleteVectorBuckets3vectors:PutVectorBucketPolicys3vectors:GetVectorBucketPolicys3vectors:DeleteVectorBucketPolicys3vectors:CreateIndexs3vectors:GetIndexs3vectors:ListIndexess3vectors:DeleteIndexs3vectors:PutVectorss3vectors:GetVectorss3vectors:ListVectorss3vectors:QueryVectorss3vectors:DeleteVectors
The resource of a policy statement is the ARN of the vector bucket or of the index. For example:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"AWS": ["arn:aws:iam::usfolks:user/fred"]},
"Action": ["s3vectors:QueryVectors", "s3vectors:GetVectors"],
"Resource": ["arn:aws:s3vectors:::bucket/my-vectors/index/my-index"]
}]
}
Note
Anonymous access to the S3 Vectors API is not allowed.
Brought to you by the Ceph Foundation
The Ceph Documentation is a community resource funded and hosted by the non-profit Ceph Foundation. If you would like to support this and our other efforts, please consider joining now.