Skip to content

Commit

Permalink
Add REST interface to update/delete optional named vectors (qdrant#1836)
Browse files Browse the repository at this point in the history
* Add update/delete REST endpoints

* Add update/delete vector REST endpoints to OpenAPI specification

* Fix update vector with no changes not triggering a validation error

* Update OpenAPI specification for updated request type
  • Loading branch information
timvisee authored and generall committed May 17, 2023
1 parent 5805811 commit f9b679a
Show file tree
Hide file tree
Showing 6 changed files with 385 additions and 6 deletions.
246 changes: 246 additions & 0 deletions docs/redoc/master/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -2606,6 +2606,200 @@
}
}
},
"/collections/{collection_name}/points/vectors": {
"put": {
"tags": [
"points"
],
"summary": "Update vectors",
"description": "Update specified named vectors on points, keep unspecified vectors intact.",
"operationId": "update_vectors",
"requestBody": {
"description": "Update named vectors on points",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateVectors"
}
}
}
},
"parameters": [
{
"name": "collection_name",
"in": "path",
"description": "Name of the collection to update from",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "wait",
"in": "query",
"description": "If true, wait for changes to actually happen",
"required": false,
"schema": {
"type": "boolean"
}
},
{
"name": "ordering",
"in": "query",
"description": "define ordering guarantees for the operation",
"required": false,
"schema": {
"$ref": "#/components/schemas/WriteOrdering"
}
}
],
"responses": {
"default": {
"description": "error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"4XX": {
"description": "error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"200": {
"description": "successful operation",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"time": {
"type": "number",
"format": "float",
"description": "Time spent to process this request"
},
"status": {
"type": "string",
"enum": [
"ok"
]
},
"result": {
"$ref": "#/components/schemas/UpdateResult"
}
}
}
}
}
}
}
}
},
"/collections/{collection_name}/points/vectors/delete": {
"post": {
"tags": [
"points"
],
"summary": "Delete vectors",
"description": "Delete named vectors from the given points.",
"operationId": "delete_vectors",
"requestBody": {
"description": "Delete named vectors from points",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DeleteVectors"
}
}
}
},
"parameters": [
{
"name": "collection_name",
"in": "path",
"description": "Name of the collection to delete from",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "wait",
"in": "query",
"description": "If true, wait for changes to actually happen",
"required": false,
"schema": {
"type": "boolean"
}
},
{
"name": "ordering",
"in": "query",
"description": "define ordering guarantees for the operation",
"required": false,
"schema": {
"$ref": "#/components/schemas/WriteOrdering"
}
}
],
"responses": {
"default": {
"description": "error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"4XX": {
"description": "error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
}
}
}
},
"200": {
"description": "successful operation",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"time": {
"type": "number",
"format": "float",
"description": "Time spent to process this request"
},
"status": {
"type": "string",
"enum": [
"ok"
]
},
"result": {
"$ref": "#/components/schemas/UpdateResult"
}
}
}
}
}
}
}
}
},
"/collections/{collection_name}/points/payload": {
"post": {
"tags": [
Expand Down Expand Up @@ -7311,6 +7505,58 @@
"quorum",
"all"
]
},
"UpdateVectors": {
"type": "object",
"required": [
"points"
],
"properties": {
"points": {
"description": "Points with named vectors",
"type": "array",
"items": {
"$ref": "#/components/schemas/PointVectors"
},
"minItems": 1
}
}
},
"PointVectors": {
"type": "object",
"required": [
"id",
"vector"
],
"properties": {
"id": {
"$ref": "#/components/schemas/ExtendedPointId"
},
"vector": {
"$ref": "#/components/schemas/VectorStruct"
}
}
},
"DeleteVectors": {
"type": "object",
"required": [
"point_selector",
"vector"
],
"properties": {
"point_selector": {
"$ref": "#/components/schemas/PointsSelector"
},
"vector": {
"description": "Vector names",
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
}
}
}
}
Expand Down
8 changes: 3 additions & 5 deletions lib/collection/src/operations/vector_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,9 @@ impl SplitByShard for VectorOperations {
}

/// Validate the vector struct is not empty.
pub fn validate_vector_struct_not_empty(value: &VectorStruct) -> Result<(), ValidationError> {
// If any vector is specified we're good
match value {
VectorStruct::Multi(vectors) if vectors.is_empty() => {}
VectorStruct::Single(_) | VectorStruct::Multi(_) => return Ok(()),
fn validate_vector_struct_not_empty(value: &VectorStruct) -> Result<(), ValidationError> {
if !value.is_empty() {
return Ok(());
}

let mut err = ValidationError::new("length");
Expand Down
10 changes: 10 additions & 0 deletions lib/segment/src/data_types/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ pub enum VectorStruct {
Multi(HashMap<String, VectorType>),
}

impl VectorStruct {
/// Check if this vector struct is empty.
pub fn is_empty(&self) -> bool {
match self {
VectorStruct::Single(vector) => vector.is_empty(),
VectorStruct::Multi(vectors) => vectors.values().all(|v| v.is_empty()),
}
}
}

impl From<VectorType> for VectorStruct {
fn from(v: VectorType) -> Self {
VectorStruct::Single(v)
Expand Down
70 changes: 70 additions & 0 deletions openapi/openapi-points.ytt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,76 @@ paths:
$ref: "#/components/schemas/WriteOrdering"
responses: #@ response(reference("UpdateResult"))

/collections/{collection_name}/points/vectors:
put:
tags:
- points
summary: Update vectors
description: Update specified named vectors on points, keep unspecified vectors intact.
operationId: update_vectors
requestBody:
description: Update named vectors on points
content:
application/json:
schema:
$ref: "#/components/schemas/UpdateVectors"

parameters:
- name: collection_name
in: path
description: Name of the collection to update from
required: true
schema:
type: string
- name: wait
in: query
description: "If true, wait for changes to actually happen"
required: false
schema:
type: boolean
- name: ordering
in: query
description: "define ordering guarantees for the operation"
required: false
schema:
$ref: "#/components/schemas/WriteOrdering"
responses: #@ response(reference("UpdateResult"))

/collections/{collection_name}/points/vectors/delete:
post:
tags:
- points
summary: Delete vectors
description: Delete named vectors from the given points.
operationId: delete_vectors
requestBody:
description: Delete named vectors from points
content:
application/json:
schema:
$ref: "#/components/schemas/DeleteVectors"

parameters:
- name: collection_name
in: path
description: Name of the collection to delete from
required: true
schema:
type: string
- name: wait
in: query
description: "If true, wait for changes to actually happen"
required: false
schema:
type: boolean
- name: ordering
in: query
description: "define ordering guarantees for the operation"
required: false
schema:
$ref: "#/components/schemas/WriteOrdering"
responses: #@ response(reference("UpdateResult"))

/collections/{collection_name}/points/payload:
post:
tags:
Expand Down
Loading

0 comments on commit f9b679a

Please sign in to comment.