Pontos

Pontos são as entidades principais manipuladas pelo Qdrant. Um ponto é um registro composto por um vetor e um payload opcional.

Você pode procurar pontos agrupados em uma coleção com base na similaridade de vetores. Uma descrição mais detalhada do processo é fornecida na seção de Pesquisa e Filtro.

Esta seção apresenta como criar e gerenciar vetores.

Qualquer operação de modificação em um ponto é assíncrona e dividida em duas etapas. Na primeira etapa, a operação será gravada em um log de gravação antecipada.

Neste momento, mesmo que a máquina perca energia, o serviço não perderá dados.

Dica: Pontos são um conceito abstrato no Qdrant, você pode pensá-los como uma linha de dados em uma tabela MySQL.

Aguardando Resultados

Se a API for chamada com o parâmetro &wait=false, ou não for explicitamente especificado, o cliente receberá uma mensagem de confirmação para recepção de dados:

{
    "result": {
        "operation_id": 123,
        "status": "acknowledged"
    },
    "status": "ok",
    "time": 0.000206061
}

Esta resposta não garante a recuperação imediata dos dados. Ela utiliza uma forma de consistência eventual. Pode levar algum tempo durante o processo real de atualização da coleção. Na realidade, esta solicitação pode falhar no final. Se estiver inserindo um grande número de vetores, também recomendamos o uso de solicitações assíncronas para utilizar totalmente as operações em pipeline.

Se a lógica da sua aplicação exigir disponibilidade imediata para pesquisa após a resposta da API, use a flag ?wait=true. Neste caso, a API só retornará o resultado após a conclusão da operação:

{
    "result": {
        "operation_id": 0,
        "status": "completed"
    },
    "status": "ok",
    "time": 0.000206061
}

ID do Ponto

O Qdrant suporta o uso de inteiros não assinados de 64 bits e UUIDs como identificadores para pontos.

Exemplos de representações de string de UUID são os seguintes:

  • Representação simples: 936DA01F9ABD4d9d80C702AF85C822A8
  • Representação com hífens: 550e8400-e29b-41d4-a716-446655440000
  • URN: urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4

Isso significa que em cada solicitação, strings de UUID podem ser usadas em vez de IDs numéricos. Por exemplo:

PUT /collections/{collection_name}/points

{
    "points": [
        {
            "id": "5c56c793-69f3-4fbf-87e6-c4bf54c28c26",
            "payload": {"color": "red"},
            "vector": [0.9, 0.1, 0.1]
        }
    ]
}

e

PUT /collections/{collection_name}/points

{
    "points": [
        {
            "id": 1,
            "payload": {"color": "red"},
            "vector": [0.9, 0.1, 0.1]
        }
    ]
}

são ambos válidos.

Carregando Pontos de Dados

Para otimizar o desempenho, o Qdrant suporta o carregamento em lote de pontos de dados. Isso significa que você pode carregar vários pontos de dados no serviço em uma única chamada de API. O carregamento em lote pode reduzir significativamente o overhead de conexão de rede.

A API do Qdrant suporta dois métodos de criação em lote - orientado a registro e orientado a coluna. Internamente, essas opções são indistinguíveis e são simplesmente para conveniência na interação.

Criando pontos de dados usando a API REST:

PUT /collections/{collection_name}/points

{
    "batch": {
        "ids": [1, 2, 3],
        "payloads": [
            {"color": "red"},
            {"color": "green"},
            {"color": "blue"}
        ],
        "vectors": [
            [0.9, 0.1, 0.1],
            [0.1, 0.9, 0.1],
            [0.1, 0.1, 0.9]
        ]
    }
}

Ou use o método equivalente utilizando a abordagem orientada a registro:

PUT /collections/{collection_name}/points

{
    "points": [
        {
            "id": 1,
            "payload": {"color": "red"},
            "vector": [0.9, 0.1, 0.1]
        },
        {
            "id": 2,
            "payload": {"color": "green"},
            "vector": [0.1, 0.9, 0.1]
        },
        {
            "id": 3,
            "payload": {"color": "blue"},
            "vector": [0.1, 0.1, 0.9]
        }
    ]
}

Todas as APIs no Qdrant, incluindo o carregamento de pontos de dados, são idempotentes. Isso significa que a realização do mesmo método consecutivamente é equivalente a uma única execução.

Neste cenário, isso significa que ao reenviar pontos de dados com o mesmo ID, os pontos de dados existentes serão sobrescritos.

A propriedade idempotente é útil para o uso de filas de mensagens que não oferecem garantias precisas de execução única. Mesmo nesse caso, o Qdrant garante a consistência dos dados.

Disponível desde a versão v0.10.0

Se uma coleção que está sendo criada possui múltiplos vetores, você pode fornecer dados para cada vetor nomeando os vetores:

PUT /collections/{collection_name}/points

{
    "points": [
        {
            "id": 1,
            "vector": {
                "imagem": [0.9, 0.1, 0.1, 0.2],
                "texto": [0.4, 0.7, 0.1, 0.8, 0.1, 0.1, 0.9, 0.2]
            }
        },
        {
            "id": 2,
            "vector": {
                "imagem": [0.2, 0.1, 0.3, 0.9],
                "texto": [0.5, 0.2, 0.7, 0.4, 0.7, 0.2, 0.3, 0.9]
            }
        }
    ]
}

Disponível desde a versão v1.2.0

Vetores nomeados são opcionais. Ao carregar pontos de dados, alguns vetores podem ser omitidos. Por exemplo, você pode carregar um ponto de dados apenas com o vetor imagem e outro apenas com o vetor texto.

Ao modificar um ponto de dados com um ID existente, o ponto de dados existente é primeiro excluído e então é reinserido com o vetor especificado. Em outras palavras, o ponto de dados inteiro será substituído, e quaisquer vetores não especificados serão definidos como nulos. Se desejar manter os vetores existentes inalterados e apenas atualizar vetores específicos, consulte a atualização de vetores.

Modificando Pontos de Dados

Para modificar um ponto de dados, você pode modificar seu vetor ou sua carga útil. Existem vários métodos para alcançar isso.

Atualizar Vetores

Disponível a partir da versão v1.2.0

Este método atualiza os vetores especificados nos pontos fornecidos. Os vetores não especificados permanecerão inalterados. Todos os pontos fornecidos devem existir.

API REST (Esquema):

PUT /collections/{collection_name}/points/vectors

{
    "points": [
        {
            "id": 1,
            "vector": {
                "imagem": [0.1, 0.2, 0.3, 0.4]
            }
        },
        {
            "id": 2,
            "vector": {
                "texto": [0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2]
            }
        }
    ]
}

Para atualizar pontos e substituir todos os vetores, consulte a operação de carregamento de pontos.

Excluir Vetores

Disponível a partir da versão v1.2.0

Este método apenas exclui os vetores especificados dos pontos fornecidos. Outros vetores permanecerão inalterados. Os pontos não serão excluídos.

API REST (Esquema):

POST /collections/{collection_name}/points/vectors/delete

{
    "points": [0, 3, 100],
    "vectors": ["texto", "imagem"]
}

Definir Carga Útil

Defina os valores de carga útil fornecidos nos pontos.

API REST (Esquema):

POST /collections/{collection_name}/points/payload

{
    "payload": {
        "propriedade1": "string",
        "propriedade2": "string"
    },
    "points": [
        0, 3, 100
    ]
}

Você não precisa saber o id do ponto a ser modificado. Outra maneira é usar filtros.

POST /collections/{collection_name}/points/payload

{
    "payload": {
        "propriedade1": "string",
        "propriedade2": "string"
    },
    "filter": {
        "must": [
            {
                "key": "cor",
                "match": {
                    "value": "vermelho"
                }
            }
        ]
    }
}

Sobrescrever Carga Útil

Substitua completamente a carga útil existente pela carga útil fornecida.

API REST (Esquema):

PUT /collections/{collection_name}/points/payload

{
    "payload": {
        "propriedade1": "string",
        "propriedade2": "string"
    },
    "points": [
        0, 3, 100
    ]
}

Similar a Definir Carga Útil, você não precisa saber o id do ponto a ser modificado. Outra maneira é usar filtros.

Excluir Chaves de Carga Útil

API REST (Esquema):

POST /collections/{collection_name}/points/payload/delete

{
    "keys": ["cor", "preço"],
    "points": [0, 3, 100]
}

Alternativamente, você pode usar filtros para excluir chaves de carga útil dos pontos.

POST /collections/{collection_name}/points/payload/delete

{
    "keys": ["cor", "preço"],
    "filter": {
        "must": [
            {
                "key": "cor",
                "match": {
                    "value": "vermelho"
                }
            }
        ]
    }
}

Limpar Carga Útil

Este método remove todas as chaves de carga útil dos pontos especificados.

API REST (Esquema):

POST /collections/{collection_name}/points/payload/clear

{
    "points": [0, 3, 100]
}

Excluir Pontos

REST API (Esquema):

POST /collections/{collection_name}/points/delete

{
    "points": [0, 3, 100]
}

Outra maneira de especificar os pontos a serem excluídos é usando um filtro:

POST /collections/{collection_name}/points/delete

{
    "filter": {
        "must": [
            {
                "key": "color",
                "match": {
                    "value": "red"
                }
            }
        ]
    }
}

Este exemplo exclui todos os pontos com { "color": "red" } da coleção.

Recuperar Pontos

Método para recuperar pontos pelos seus IDs:

REST API (Esquema):

POST /collections/{collection_name}/points

{
    "ids": [0, 3, 100]
}

Este método possui parâmetros adicionais with_vectors e with_payload. Utilizando esses parâmetros, você pode selecionar as partes dos resultados dos pontos que você precisa. A exclusão ajuda a evitar desperdício de transferência de dados em dados inúteis.

Também é possível recuperar um único ponto via a API:

REST API (Esquema):

GET /collections/{collection_name}/points/{point_id}

Rolagem

Às vezes é necessário recuperar todos os pontos armazenados sem saber seus IDs, ou iterar através de pontos que satisfaçam condições de filtragem.

REST API (Esquema):

POST /collections/{collection_name}/points/scroll

{
    "filter": {
        "must": [
            {
                "key": "color",
                "match": {
                    "value": "red"
                }
            }
        ]
    },
    "limit": 1,
    "with_payload": true,
    "with_vector": false
}

Retorna todos os pontos que correspondem a color = red:

{
    "result": {
        "next_page_offset": 1,
        "points": [
            {
                "id": 0,
                "payload": {
                    "color": "red"
                }
            }
        ]
    },
    "status": "ok",
    "time": 0.0001
}

A API de Rolagem retornará todos os pontos que correspondem ao filtro de maneira paginada.

Todos os pontos resultantes são ordenados por ID. Para consultar a próxima página, você precisa especificar o ID máximo descoberto no campo offset. Para conveniência, este ID também é retornado no campo next_page_offset. Se o valor do campo next_page_offset for null, significa que a última página foi alcançada.

Contagem de Pontos

Disponível a partir da versão v0.8.4

Às vezes, é útil saber apenas quantos pontos correspondem às condições de filtragem sem realmente realizar uma pesquisa.

Por exemplo, isso pode ser útil nos seguintes cenários:

  • Estimar o tamanho do resultado para pesquisa facetada
  • Determinar o número de páginas para paginação
  • Depurar a velocidade de execução da consulta

REST API (Esquema):

POST /collections/{collection_name}/points/count

{
    "filter": {
        "must": [
            {
                "key": "color",
                "match": {
                    "value": "red"
                }
            }
        ]
    },
    "exact": true
}

Retorna a contagem de pontos que correspondem às condições de filtragem fornecidas:

{
    "count": 3811
}

Atualização em Lote

Disponível a partir da versão v1.5.0

Você pode realizar operações em lote em vários pontos. Isso inclui a inserção, atualização e exclusão de pontos, vetores e cargas úteis.

Uma solicitação de atualização em lote consiste em uma série de operações que são executadas sequencialmente. As operações que podem ser incluídas em lotes são:

  • Inserir ou atualizar pontos: upsert ou UpsertOperation
  • Excluir pontos: delete_points ou DeleteOperation
  • Atualizar vetores: update_vectors ou UpdateVectorsOperation
  • Excluir vetores: delete_vectors ou DeleteVectorsOperation
  • Definir carga útil: set_payload ou SetPayloadOperation
  • Sobrescrever carga útil: overwrite_payload ou OverwritePayload
  • Excluir carga útil: delete_payload ou DeletePayloadOperation
  • Limpar a carga útil: clear_payload ou ClearPayloadOperation

O trecho de código de exemplo a seguir utiliza todas as operações.

API REST (Esquema):

POST /collections/{collection_name}/points/batch

{
    "operations": [
        {
            "upsert": {
                "points": [
                    {
                        "id": 1,
                        "vector": [1.0, 2.0, 3.0, 4.0],
                        "payload": {}
                    }
                ]
            }
        },
        {
            "update_vectors": {
                "points": [
                    {
                        "id": 1,
                        "vector": [1.0, 2.0, 3.0, 4.0]
                    }
                ]
            }
        },
        {
            "delete_vectors": {
                "points": [1],
                "vector": [""]
            }
        },
        {
            "overwrite_payload": {
                "payload": {
                    "test_payload": "1"
                },
                "points": [1]
            }
        },
        {
            "set_payload": {
                "payload": {
                    "test_payload_2": "2",
                    "test_payload_3": "3"
                },
                "points": [1]
            }
        },
        {
            "delete_payload": {
                "keys": ["test_payload_2"],
                "points": [1]
            }
        },
        {
            "clear_payload": {
                "points": [1]
            }
        },
        {"delete": {"points": [1]}}
    ]
}

Para usar pontos em lote com um único tipo de operação, use o recurso em lote diretamente dentro dessa operação.