Puntos

Los puntos son las entidades centrales manipuladas por Qdrant. Un punto es un registro compuesto por un vector y una carga útil opcional.

Puede buscar puntos agrupados en una colección basada en la similitud de vectores. Una descripción más detallada del proceso se proporciona en la sección de Búsqueda y Filtro.

Esta sección introduce cómo crear y gestionar vectores.

Cualquier operación de modificación en un punto es asíncrona y se divide en dos pasos. En la primera etapa, la operación se escribirá en un registro de transacciones.

En este momento, incluso si la máquina se apaga, el servicio no perderá datos.

Consejo: Los puntos son un concepto abstracto en Qdrant, puede pensar en ellos como una fila de datos en una tabla MySQL.

Esperando Resultados

Si se llama a la API con el parámetro &wait=false, o no se especifica de manera explícita, el cliente recibirá un mensaje de confirmación para la recepción de datos:

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

Esta respuesta no garantiza la recuperación inmediata de los datos. Utiliza una forma de consistencia eventual. Puede llevar algún tiempo durante el proceso real de actualización de la colección. En realidad, esta solicitud puede fallar en última instancia. Si está insertando un gran número de vectores, también recomendamos usar solicitudes asíncronas para aprovechar completamente las operaciones en la cola.

Si la lógica de su aplicación requiere disponibilidad inmediata para la búsqueda después de la respuesta de la API, utilice la bandera ?wait=true. En este caso, la API solo devolverá el resultado después de que la operación se haya completado:

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

ID del Punto

Qdrant admite el uso de enteros sin signo de 64 bits y UUIDs como identificadores de puntos.

Ejemplos de representaciones de cadenas de UUID son los siguientes:

  • Representación simple: 936DA01F9ABD4d9d80C702AF85C822A8
  • Representación con guiones: 550e8400-e29b-41d4-a716-446655440000
  • URN: urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4

Esto significa que en cada solicitud, se pueden utilizar cadenas de UUID en lugar de identificadores numéricos. Por ejemplo:

PUT /colecciones/{nombre_de_colección}/puntos

{
    "puntos": [
        {
            "id": "5c56c793-69f3-4fbf-87e6-c4bf54c28c26",
            "carga_útil": {"color": "rojo"},
            "vector": [0.9, 0.1, 0.1]
        }
    ]
}

y

PUT /colecciones/{nombre_de_colección}/puntos

{
    "puntos": [
        {
            "id": 1,
            "carga_útil": {"color": "rojo"},
            "vector": [0.9, 0.1, 0.1]
        }
    ]
}

son válidos.

Carga de puntos de datos

Para optimizar el rendimiento, Qdrant admite la carga por lotes de puntos de datos. Esto significa que puedes cargar varios puntos de datos en el servicio en una sola llamada a la API. La carga por lotes puede reducir significativamente la sobrecarga de conexión de red.

La API de Qdrant admite dos métodos de creación por lotes: orientados a registro y orientados a columna. Internamente, estas opciones son indistinguibles y simplemente son convenientes para la interacción.

Creación de puntos de datos usando la API REST:

PUT /collections/{nombre_de_colección}/puntos

{
    "lote": {
        "ids": [1, 2, 3],
        "cargas": [
            {"color": "rojo"},
            {"color": "verde"},
            {"color": "azul"}
        ],
        "vectores": [
            [0.9, 0.1, 0.1],
            [0.1, 0.9, 0.1],
            [0.1, 0.1, 0.9]
        ]
    }
}

O utiliza el método equivalente utilizando el enfoque orientado a registro:

PUT /collections/{nombre_de_colección}/puntos

{
    "puntos": [
        {
            "id": 1,
            "carga": {"color": "rojo"},
            "vector": [0.9, 0.1, 0.1]
        },
        {
            "id": 2,
            "carga": {"color": "verde"},
            "vector": [0.1, 0.9, 0.1]
        },
        {
            "id": 3,
            "carga": {"color": "azul"},
            "vector": [0.1, 0.1, 0.9]
        }
    ]
}

Todas las API en Qdrant, incluida la carga de puntos de datos, son idempotentes. Esto significa que realizar el mismo método consecutivamente es equivalente a una ejecución única.

En este escenario, esto significa que al volver a cargar los puntos de datos con el mismo ID, los puntos de datos existentes serán sobrescritos.

La propiedad idempotente es útil para usar colas de mensajes que no proporcionan garantías precisas de "solo una vez". Incluso en este caso, Qdrant asegura la consistencia de los datos.

Disponible desde v0.10.0

Si una colección que se está creando tiene varios vectores, puedes proporcionar datos para cada vector nombrándolos:

PUT /collections/{nombre_de_colección}/puntos

{
    "puntos": [
        {
            "id": 1,
            "vector": {
                "imagen": [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": {
                "imagen": [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]
            }
        }
    ]
}

Disponible desde v1.2.0

Los vectores nombrados son opcionales. Al cargar puntos de datos, algunos vectores pueden ser omitidos. Por ejemplo, puedes cargar un punto de datos con solo el vector "imagen" y otro con solo el vector "texto".

Al modificar un punto de datos con un ID existente, primero se elimina el punto de datos existente y luego se vuelve a insertar con el vector especificado. En otras palabras, el punto de datos completo será reemplazado y cualquier vector no especificado se establecerá como nulo. Si deseas mantener inalterados los vectores existentes y solo actualizar los vectores especificados, consulta la actualización de vectores.

Modificación de puntos de datos

Para modificar un punto de datos, puedes modificar su vector o su carga útil. Hay varios métodos para lograr esto.

Actualizar Vectores

Disponible desde la versión v1.2.0

Este método actualiza los vectores especificados en los puntos dados. Los vectores no especificados permanecerán sin cambios. Todos los puntos dados deben existir.

REST API (Esquema):

PUT /colecciones/{nombre_coleccion}/puntos/vectores

{
    "puntos": [
        {
            "id": 1,
            "vector": {
                "imagen": [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 actualizar puntos y reemplazar todos los vectores, consulte la operación de carga de puntos.

Eliminar Vectores

Disponible desde la versión v1.2.0

Este método solo elimina los vectores especificados de los puntos dados. Otros vectores permanecerán sin cambios. Los puntos no se eliminarán.

REST API (Esquema):

POST /colecciones/{nombre_coleccion}/puntos/vectores/eliminar

{
    "puntos": [0, 3, 100],
    "vectores": ["texto", "imagen"]
}

Establecer Carga Útil

Establecer los valores de carga útil dados en puntos.

REST API (Esquema):

POST /colecciones/{nombre_coleccion}/puntos/carga_util

{
    "carga_util": {
        "propiedad1": "cadena",
        "propiedad2": "cadena"
    },
    "puntos": [
        0, 3, 100
    ]
}

No es necesario conocer el id del punto a modificar. Otra forma es utilizar filtros.

POST /colecciones/{nombre_coleccion}/puntos/carga_util

{
    "carga_util": {
        "propiedad1": "cadena",
        "propiedad2": "cadena"
    },
    "filtro": {
        "debe": [
            {
                "clave": "color",
                "coincidencia": {
                    "valor": "rojo"
                }
            }
        ]
    }
}

Sobrescribir Carga Útil

Reemplazar completamente la carga útil existente con la carga útil dada.

REST API (Esquema):

PUT /colecciones/{nombre_coleccion}/puntos/carga_util

{
    "carga_util": {
        "propiedad1": "cadena",
        "propiedad2": "cadena"
    },
    "puntos": [
        0, 3, 100
    ]
}

Similar a Establecer Carga Útil, no es necesario conocer el id del punto a modificar. Otra forma es utilizar filtros.

Eliminar Claves de Carga Útil

REST API (Esquema):

POST /colecciones/{nombre_coleccion}/puntos/carga_util/eliminar

{
    "claves": ["color", "precio"],
    "puntos": [0, 3, 100]
}

Alternativamente, puedes utilizar filtros para eliminar claves de carga útil de puntos.

POST /colecciones/{nombre_coleccion}/puntos/carga_util/eliminar

{
    "claves": ["color", "precio"],
    "filtro": {
        "debe": [
            {
                "clave": "color",
                "coincidencia": {
                    "valor": "rojo"
                }
            }
        ]
    }
}

Limpiar Carga Útil

Este método elimina todas las claves de carga útil de los puntos especificados.

REST API (Esquema):

POST /colecciones/{nombre_coleccion}/puntos/carga_util/limpiar

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

Eliminar puntos

API REST (Esquema):

POST /collections/{nombre_colección}/points/delete

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

Otra forma de especificar los puntos a eliminar es mediante el uso de un filtro:

POST /collections/{nombre_colección}/points/delete

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

Este ejemplo elimina todos los puntos con { "color": "rojo" } de la colección.

Recuperar puntos

Método para recuperar puntos por sus identificadores:

API REST (Esquema):

POST /collections/{nombre_colección}/points

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

Este método tiene parámetros adicionales with_vectors y with_payload. Utilizando estos parámetros, puedes seleccionar las partes de los resultados de los puntos que necesitas. Excluir ayuda a evitar el desperdicio de transferencia de datos en datos inútiles.

También es posible recuperar un solo punto a través de la API:

API REST (Esquema):

GET /collections/{nombre_colección}/points/{id_punto}

Desplazamiento

A veces es necesario recuperar todos los puntos almacenados sin conocer sus identificadores, o iterar a través de puntos que satisfacen condiciones de filtrado.

API REST (Esquema):

POST /collections/{nombre_colección}/points/scroll

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

Devuelve todos los puntos que coinciden con color=rojo:

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

La API de Desplazamiento devolverá todos los puntos que coincidan con el filtro de manera paginada.

Todos los puntos resultantes están ordenados por ID. Para consultar la siguiente página, debes especificar el ID máximo descubierto en el campo offset. Para mayor comodidad, este ID también se devuelve en el campo next_page_offset. Si el valor del campo next_page_offset es null, significa que se ha alcanzado la última página.

Contar puntos

Disponible desde la versión v0.8.4

A veces es útil solo saber cuántos puntos coinciden con las condiciones de filtrado sin realizar una búsqueda real.

Por ejemplo, esto puede ser útil en los siguientes escenarios:

  • Estimando el tamaño del resultado para la búsqueda facetada
  • Determinando el número de páginas para la paginación
  • Depuración de la velocidad de ejecución de consultas

API REST (Esquema):

POST /collections/{nombre_colección}/points/count

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

Devuelve el recuento de puntos que coinciden con las condiciones de filtrado dados:

{
    "count": 3811
}

Actualización por lotes

Disponible desde la versión v1.5.0

Puede realizar operaciones por lotes en múltiples puntos. Esto incluye la inserción, actualización y eliminación de puntos, vectores y cargas útiles.

Una solicitud de actualización por lotes consiste en una serie de operaciones que se ejecutan secuencialmente. Las operaciones que se pueden agrupar incluyen:

  • Insertar o actualizar puntos: upsert o UpsertOperation
  • Eliminar puntos: delete_points o DeleteOperation
  • Actualizar vectores: update_vectors o UpdateVectorsOperation
  • Eliminar vectores: delete_vectors o DeleteVectorsOperation
  • Establecer carga útil: set_payload o SetPayloadOperation
  • Sobrescribir carga útil: overwrite_payload o OverwritePayload
  • Eliminar carga útil: delete_payload o DeletePayloadOperation
  • Borrar carga útil: clear_payload o ClearPayloadOperation

El siguiente ejemplo de código utiliza todas las operaciones.

API REST (Esquema):

POST /collections/{nombre_colección}/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 puntos en lotes con un solo tipo de operación, utilice la función de lotes directamente dentro de esa operación.