Skip to content

Point Operations API

This document is for users of the "Point Operations" API, systematically documenting HTTP endpoints related to point operations: PUT /collections/{name}/points (Upsert points), POST /collections/{name}/points/search (Search), POST /collections/{name}/points/delete (Delete). The documentation covers:

  • Endpoint request/response patterns and field definitions
  • PointStruct structure, vector data format, filter condition syntax
  • Upsert batch insert, update, and overwrite mechanism
  • Search query parameter configuration (vector, filter, limit count)
  • Delete operation multiple methods (by ID and by filter condition)
  • Complete JSON examples and error handling descriptions

Project Structure

The service uses a layered design:

  • API Layer: Responsible for routing and HTTP protocol encoding/decoding
  • Core Layer: Collection, Index, Storage and other business logic
  • Storage Layer: bbolt-based local persistence with Protobuf serialization
graph TB
subgraph "API Layer"
S["Server
Routing and HTTP handling"] end subgraph "Core Layer" C["Collection
Collection management"] I["VectorIndex
Index interface"] F["Flat/HNSW Index"] M["Models
PointStruct/Filter/ScoredPoint"] D["Distance
Cosine/Euclid/Dot"] end subgraph "Storage Layer" ST["Storage
bbolt + Protobuf"] end S --> C C --> I I --> F C --> ST M --> D

Core Components

  • Server: HTTP routing and request handling, exposing point operation endpoints
  • Collection: Collection abstraction encapsulating Upsert/Search/Delete business logic
  • VectorIndex Interface: Unified index capabilities (Upsert/Search/Delete/Count/Filter)
  • Storage: Local persistence supporting bbolt and Protobuf serialization
  • Models: Data models (PointStruct, Filter, ScoredPoint) and matching algorithms
  • Distance: Distance metrics (Cosine/Euclid/Dot)

Architecture Overview

The call chain for Point Operations API is as follows:

sequenceDiagram
participant Client as "Client"
participant API as "Server.handleUpsert/Search/Delete"
participant Col as "Collection"
participant Idx as "VectorIndex"
participant St as "Storage"
Client->>API : "PUT /collections/{name}/points"
Request body: {points : [PointStruct]} API->>Col : "Upsert(points)" Col->>St : "UpsertPoints(collection, points)" Col->>Idx : "Upsert(points)" Idx-->>Col : "OK" St-->>Col : "OK" Col-->>API : "OK" API-->>Client : "{status : 'ok', result : {operation : 'completed'}}" Client->>API : "POST /collections/{name}/points/search"
Request body: {vector : [], filter?, limit : int} API->>Col : "Search(vector, filter, limit)" Col->>Idx : "Search(vector, filter, limit)" Idx-->>Col : "[]ScoredPoint" Col-->>API : "[]ScoredPoint" API-->>Client : "{status : 'ok', result : []}" Client->>API : "POST /collections/{name}/points/delete"
Request body: {points : [], filter?} API->>Col : "Delete(points, filter)" Col->>St : "DeletePoints(collection, ids)" Col->>Idx : "Delete(id) for each id" Idx-->>Col : "OK" St-->>Col : "OK" Col-->>API : "deleted : int" API-->>Client : "{status : 'ok', result : {operation : 'completed', deleted : int}}"

Detailed Component Analysis

Point Structure and Filter Model

  • PointStruct: Contains unique identifier, version number, vector, optional payload (for filtering)
  • ScoredPoint: Search result containing similarity score and point information
  • Filter: Supports must/must_not conditions; condition types include exact, range, prefix, contains, regex
  • Distance: Supports Cosine, Euclid, Dot three metrics
classDiagram
class PointStruct {
    +string id
    +uint64 version
    +[]float32 vector
    +map[string]interface{} payload
}
class ScoredPoint {
    +string id
    +uint64 version
    +float32 score
    +map[string]interface{} payload
}
class Filter {
    +[]Condition must
    +[]Condition must_not
}
class Condition {
    +string key
    +string type
    +MatchValue match
    +RangeValue range
}
class MatchValue {
    +interface{} value
}
class RangeValue {
    +interface{} gt
    +interface{} gte
    +interface{} lt
    +interface{} lte
}
class Distance {
    <>
    +Cosine
    +Euclid
    +Dot
}
ScoredPoint --> PointStruct : "contains"
Filter --> Condition : "combines"
Condition --> MatchValue : "match value"
Condition --> RangeValue : "range value"
Collection ..> Distance : "uses"

Upsert Points (PUT /collections/{name}/points)

  • Function: Batch insert or update points; returns 404 if collection does not exist; returns 400 if request body is not valid JSON; returns 500 for internal errors
  • Request body fields
  • points: array, elements are PointStruct
  • Response body fields
  • status: string, fixed as "ok"
  • result.operation: string, fixed as "completed"
  • Processing flow
  • Parse JSON → Validate collection exists → Call Collection.Upsert → Return 200 OK on success
sequenceDiagram
participant Client as "Client"
participant API as "Server.handleUpsert"
participant Col as "Collection"
participant St as "Storage"
participant Idx as "VectorIndex"
Client->>API : "PUT /collections/{name}/points"
{points : [PointStruct]} API->>API : "ParseJSON" API->>Col : "Upsert(points)" Col->>St : "UpsertPoints(name, points)" Col->>Idx : "Upsert(points)" Idx-->>Col : "OK" St-->>Col : "OK" Col-->>API : "OK" API-->>Client : "{status : 'ok', result : {operation : 'completed'}}"

Search (POST /collections/{name}/points/search)

  • Function: Similarity search based on vector, supports optional filter and limit count
  • Request body fields
  • vector: array of floats, dimension must match collection
  • filter: optional, Filter object
  • limit: integer, return top K results, default 10
  • Response body fields
  • status: string, fixed as "ok"
  • result: array, elements are ScoredPoint
  • Processing flow
  • Parse JSON → Validate collection exists → Validate vector dimension → Call Collection.Search → Return 200 OK
sequenceDiagram
participant Client as "Client"
participant API as "Server.handleSearch"
participant Col as "Collection"
participant Idx as "VectorIndex"
Client->>API : "POST /collections/{name}/points/search"
{vector : [], filter?, limit : int} API->>API : "ParseJSON" API->>Col : "Search(vector, filter, limit)" Col->>Idx : "Search(vector, filter, limit)" Idx-->>Col : "[]ScoredPoint" Col-->>API : "[]ScoredPoint" API-->>Client : "{status : 'ok', result : []}"

Delete (POST /collections/{name}/points/delete)

  • Function: Supports delete by ID or delete by filter condition; at least one must be provided
  • Request body fields
  • points: optional, string array, specifies point IDs to delete
  • filter: optional, Filter object, matches points to delete
  • Response body fields
  • status: string, fixed as "ok"
  • result.operation: string, fixed as "completed"
  • result.deleted: integer, actual number of points deleted
  • Processing flow
  • Parse JSON → Validate collection exists → Calculate target ID list (ID or derived through filter) → Delete from storage first then from index → Return 200 OK
sequenceDiagram
participant Client as "Client"
participant API as "Server.handleDelete"
participant Col as "Collection"
participant St as "Storage"
participant Idx as "VectorIndex"
Client->>API : "POST /collections/{name}/points/delete"
{points : [], filter?} API->>API : "ParseJSON" API->>Col : "Delete(points, filter)" alt points provided Col->>St : "DeletePoints(name, ids)" Col->>Idx : "Delete(id) for each id" else filter provided Col->>Idx : "GetIDsByFilter(filter)" Col->>St : "DeletePoints(name, ids)" Col->>Idx : "Delete(id) for each id" end Idx-->>Col : "OK" St-->>Col : "OK" Col-->>API : "deleted : int" API-->>Client : "{status : 'ok', result : {operation : 'completed', deleted : int}}"

Filter Syntax and Matching Rules

  • Filter
  • must: all conditions must be satisfied
  • must_not: no condition can be satisfied
  • Condition
  • key: key name in payload
  • type: match type
    • exact: exact equality
    • range: numeric range comparison (gt/gte/lt/lte)
    • prefix: string prefix match
    • contains: array/string contains
    • regex: regular expression match
  • match: match value
  • range: range value object
  • Matching algorithm
  • Numeric range: supports int and float64
  • String prefix: length check
  • Array/string contains: item-by-item comparison
  • Regex: compile and match
flowchart TD
Start(["Enter filter matching"]) --> Nil{"Filter is empty?"}
Nil --> |Yes| TrueAll["Return true, all match"]
Nil --> |No| Must["Iterate must conditions"]
Must --> MustAll{"All satisfied?"}
MustAll --> |No| FalseAll["Return false"]
MustAll --> |Yes| MustNot["Iterate must_not conditions"]
MustNot --> None{"Any satisfied?"}
None --> |Yes| FalseAll
None --> |No| TrueAll

Vector Data Format and Metrics

  • Vector: []float32, dimension must match collection
  • Metrics:
  • Cosine: [-1, 1], larger value means more similar
  • Euclid: [0, +∞), smaller value means more similar
  • Dot: (-∞, +∞), larger value means more similar
  • Default metric is Cosine

Endpoints and Error Codes

  • PUT /collections/{name}/points
  • 200: Success
  • 400: Invalid JSON
  • 404: Collection does not exist
  • 500: Internal error
  • POST /collections/{name}/points/search
  • 200: Success
  • 400: Invalid JSON
  • 404: Collection does not exist
  • 500: Internal error
  • POST /collections/{name}/points/delete
  • 200: Success
  • 400: Invalid JSON
  • 404: Collection does not exist
  • 500: Internal error

Dependency Analysis

  • API layer depends on Collection and Index interfaces from core layer
  • Collection depends on VectorIndex and Storage
  • Storage depends on bbolt and Protobuf
  • Models and Distance are pure data and computation layer
graph LR
API["api/server.go"] --> COL["core/collection.go"]
COL --> IDX["core/index.go"]
COL --> ST["core/storage.go"]
COL --> MOD["core/models.go"]
MOD --> MATH["core/math.go"]
ST --> PB["core/proto/point.proto"]

Performance Considerations

  • Index selection: Flat (in-memory brute force) and HNSW (graph approximate) can be switched; HNSW has better query latency in large-scale scenarios
  • Persistence order: Write to storage first then update index, ensuring consistency and recoverability
  • Vector quantization: SQ8 quantization can be enabled to reduce disk usage and loading cost
  • Query default limit: Returns top 10 results by default when limit is not explicitly set

Troubleshooting Guide

  • Collection does not exist
  • Symptom: 404 Not Found
  • Diagnosis: Confirm collection name is correct and has been created
  • JSON parsing failed
  • Symptom: 400 Bad Request
  • Diagnosis: Check if request body is valid JSON
  • Vector dimension mismatch
  • Symptom: Returns 500 Internal Server Error during Search
  • Diagnosis: Ensure vector dimension matches collection
  • Missing delete parameters
  • Symptom: Delete returns 500 Internal Server Error (prompting that points or filter must be provided)
  • Diagnosis: Provide at least one of points or filter

Conclusion

Point Operations API provides Qdrant-compatible REST interfaces covering Upsert, Search, Delete three core capabilities. Through Collection abstraction and VectorIndex interface, the system achieves balance between consistency, scalability, and performance. For production environments, it is recommended to combine HNSW index and vector quantization for optimal throughput and latency performance.

Appendix

Endpoint Definitions and Examples

  • Upsert (PUT /collections/{name}/points)
  • Request body
    • points: array, elements are PointStruct
    • id: string, unique identifier
    • version: integer, version number (auto-assigned)
    • vector: array of floats, dimension must match collection
    • payload: optional, key-value pairs for filtering
  • Response body

    • status: string, fixed as "ok"
    • result.operation: string, fixed as "completed"
  • Search (POST /collections/{name}/points/search)

  • Request body
    • vector: array of floats, dimension must match collection
    • filter: optional, Filter object
    • must: []Condition
    • must_not: []Condition
    • limit: integer, return top K results, default 10
  • Response body

    • status: string, fixed as "ok"
    • result: array, elements are ScoredPoint
    • id: string
    • version: integer
    • score: float
    • payload: optional
  • Delete (POST /collections/{name}/points/delete)

  • Request body
    • points: optional, string array, specifies point IDs to delete
    • filter: optional, Filter object, matches points to delete
  • Response body
    • status: string, fixed as "ok"
    • result.operation: string, fixed as "completed"
    • result.deleted: integer, actual number of points deleted

Filter Syntax Reference

  • exact: exact match
  • range: gt/gte/lt/lte numeric range
  • prefix: string prefix
  • contains: array/string contains
  • regex: regular expression

Example Request/Response (Path Reference)