Points

Les points sont les entités centrales manipulées par Qdrant. Un point est un enregistrement composé d'un vecteur et d'une charge utile facultative.

Vous pouvez rechercher des points regroupés dans une collection en fonction de la similarité des vecteurs. Une description plus détaillée du processus est fournie dans la section Recherche et Filtre.

Cette section présente comment créer et gérer des vecteurs.

Toute opération de modification sur un point est asynchrone et divisée en deux étapes. Dans la première étape, l'opération sera écrite dans un journal d'avance.

À ce moment, même si la machine perd de l'énergie, le service ne perdra pas de données.

Conseil : Les points sont un concept abstrait dans Qdrant, vous pouvez les considérer comme une rangée de données dans une table MySQL.

En attente de résultats

Si l'API est appelée avec le paramètre &wait=false, ou s'il n'est pas explicitement spécifié, le client recevra un message de confirmation pour la réception des données :

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

Cette réponse ne garantit pas la récupération immédiate des données. Elle utilise une forme de cohérence éventuelle. Il peut prendre un certain temps pendant le processus réel de mise à jour de la collection. En réalité, cette requête pourrait éventuellement échouer. Si vous insérez un grand nombre de vecteurs, nous recommandons également d'utiliser des requêtes asynchrones pour exploiter pleinement les opérations de pipeline.

Si la logique de votre application nécessite une disponibilité immédiate pour la recherche après la réponse de l'API, utilisez le drapeau ?wait=true. Dans ce cas, l'API ne renverra le résultat qu'après l'achèvement de l'opération :

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

ID du point

Qdrant prend en charge l'utilisation de entiers non signés sur 64 bits et de UUID comme identifiants pour les points.

Voici des exemples de représentations de chaînes UUID :

  • Représentation simple : 936DA01F9ABD4d9d80C702AF85C822A8
  • Représentation avec des tirets : 550e8400-e29b-41d4-a716-446655440000
  • URN : urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4

Cela signifie que dans chaque requête, des chaînes UUID peuvent être utilisées à la place des identifiants numériques. Par exemple :

PUT /collections/{collection_name}/points

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

et

PUT /collections/{collection_name}/points

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

sont tous les deux valides.

Transfert des points de données

Pour optimiser les performances, Qdrant prend en charge le transfert par lots de points de données. Cela signifie que vous pouvez charger plusieurs points de données dans le service en une seule appel d'API. Le transfert par lots peut réduire considérablement les frais généraux de connexion réseau.

L'API Qdrant prend en charge deux méthodes de création en lots : orientée enregistrement et orientée colonne. En interne, ces options sont indiscernables et ne sont là que pour des raisons pratiques d'interaction.

Création de points de données à l'aide de l'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 utilisez la méthode équivalente en adoptant une approche orientée enregistrement :

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]
        }
    ]
}

Toutes les API de Qdrant, y compris le chargement de points de données, sont idempotentes. Cela signifie que l'exécution répétée de la même méthode est équivalente à une seule exécution.

Dans ce scénario, cela signifie que lors du rechargement de points de données avec le même identifiant, les points de données existants seront écrasés.

La propriété idempotente est utile pour utiliser des files d'attente de messages qui ne garantissent pas une exécution précise unique. Même dans ce cas, Qdrant garantit la cohérence des données.

Disponible depuis la version v0.10.0

Si une collection en cours de création possède plusieurs vecteurs, vous pouvez fournir des données pour chaque vecteur en nommant les vecteurs :

PUT /collections/{collection_name}/points

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

Disponible depuis la version v1.2.0

Les vecteurs nommés sont facultatifs. Lors du transfert de points de données, certains vecteurs peuvent être omis. Par exemple, vous pouvez transférer un point de données avec seulement le vecteur 'image' et un autre avec seulement le vecteur 'texte'.

Lors de la modification d'un point de données avec un identifiant existant, le point de données existant est d'abord supprimé, puis réinséré avec le vecteur spécifié. En d'autres termes, le point de données entier sera remplacé et tout vecteur non spécifié sera défini sur null. Si vous souhaitez conserver les vecteurs existants inchangés et mettre à jour uniquement les vecteurs spécifiés, veuillez vous référer à la mise à jour des vecteurs.

Modification des points de données

Pour modifier un point de données, vous pouvez modifier son vecteur ou sa charge utile. Il existe plusieurs méthodes pour y parvenir.

Mettre à jour les vecteurs

Disponible à partir de la version v1.2.0

Cette méthode met à jour les vecteurs spécifiés aux points donnés. Les vecteurs non spécifiés resteront inchangés. Tous les points donnés doivent exister.

API REST (Schéma):

PUT /collections/{collection_name}/points/vectors

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

Pour mettre à jour les points et remplacer tous les vecteurs, veuillez vous référer à l'opération de chargement des points.

Supprimer les vecteurs

Disponible à partir de la version v1.2.0

Cette méthode supprime uniquement les vecteurs spécifiés des points donnés. Les autres vecteurs resteront inchangés. Les points ne seront pas supprimés.

API REST (Schéma):

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

{
    "points": [0, 3, 100],
    "vectors": ["text", "image"]
}

Définir la charge utile

Définir les valeurs de charge utile données sur les points.

API REST (Schéma):

POST /collections/{collection_name}/points/payload

{
    "payload": {
        "property1": "string",
        "property2": "string"
    },
    "points": [
        0, 3, 100
    ]
}

Vous n'avez pas besoin de connaître l'identifiant du point à modifier. Une autre méthode est d'utiliser des filtres.

POST /collections/{collection_name}/points/payload

{
    "payload": {
        "property1": "string",
        "property2": "string"
    },
    "filter": {
        "must": [
            {
                "key": "color",
                "match": {
                    "value": "red"
                }
            }
        ]
    }
}

Remplacer la charge utile

Remplacer complètement la charge utile existante avec la charge utile donnée.

API REST (Schéma):

PUT /collections/{collection_name}/points/payload

{
    "payload": {
        "property1": "string",
        "property2": "string"
    },
    "points": [
        0, 3, 100
    ]
}

Similaire à Définir la charge utile, vous n'avez pas besoin de connaître l'identifiant du point à modifier. Une autre méthode est d'utiliser des filtres.

Supprimer les clés de la charge utile

API REST (Schéma):

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

{
    "keys": ["color", "price"],
    "points": [0, 3, 100]
}

Alternativement, vous pouvez utiliser des filtres pour supprimer les clés de la charge utile des points.

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

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

Effacer la charge utile

Cette méthode supprime toutes les clés de la charge utile des points spécifiés.

API REST (Schéma):

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

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

Supprimer des points

API REST (Schéma):

POST /collections/{collection_name}/points/delete

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

Une autre façon de spécifier les points à supprimer consiste à utiliser un filtre :

POST /collections/{collection_name}/points/delete

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

Cet exemple supprime tous les points avec { "color": "red" } de la collection.

Récupérer des points

Méthode pour récupérer des points par leurs IDs :

API REST (Schéma):

POST /collections/{collection_name}/points

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

Cette méthode possède des paramètres supplémentaires with_vectors et with_payload. En utilisant ces paramètres, vous pouvez sélectionner les parties des résultats des points dont vous avez besoin. L'exclusion permet d'éviter de gaspiller le transfert de données sur des données inutiles.

Il est également possible de récupérer un seul point via l'API :

API REST (Schéma):

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

Défilement

Parfois, il est nécessaire de récupérer tous les points stockés sans connaître leurs IDs, ou d'itérer à travers des points qui satisfont des conditions de filtrage.

API REST (Schéma):

POST /collections/{collection_name}/points/scroll

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

Renvoie tous les points qui correspondent à color=red :

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

L'API de défilement renverra tous les points qui correspondent au filtre de manière paginée.

Tous les points résultants sont triés par ID. Pour interroger la page suivante, vous devez spécifier l'ID maximum découvert dans le champ offset. Pour plus de commodité, cet ID est également renvoyé dans le champ next_page_offset. Si la valeur du champ next_page_offset est null, cela signifie que la dernière page a été atteinte.

Comptage des points

Disponible à partir de la version v0.8.4

Parfois, il est utile de savoir uniquement combien de points correspondent aux conditions de filtrage sans effectuer réellement une recherche.

Par exemple, cela peut être utile dans les scénarios suivants :

  • Estimer la taille du résultat pour une recherche facettée
  • Déterminer le nombre de pages pour la pagination
  • Déboguer la vitesse d'exécution de la requête

API REST (Schéma):

POST /collections/{collection_name}/points/count

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

Renvoie le nombre de points qui correspondent aux conditions de filtrage données :

{
    "count": 3811
}

Mise à jour par lot

Disponible depuis la version 1.5.0

Vous pouvez effectuer des opérations en lot sur plusieurs points. Cela inclut l'insertion, la mise à jour et la suppression de points, de vecteurs et de charges utiles.

Une requête de mise à jour par lot consiste en une série d'opérations exécutées séquentiellement. Les opérations pouvant être regroupées comprennent :

  • Insérer ou mettre à jour des points : upsert ou UpsertOperation
  • Supprimer des points : delete_points ou DeleteOperation
  • Mettre à jour des vecteurs : update_vectors ou UpdateVectorsOperation
  • Supprimer des vecteurs : delete_vectors ou DeleteVectorsOperation
  • Définir une charge utile : set_payload ou SetPayloadOperation
  • Écraser une charge utile : overwrite_payload ou OverwritePayload
  • Supprimer une charge utile : delete_payload ou DeletePayloadOperation
  • Effacer une charge utile : clear_payload ou ClearPayloadOperation

L'exemple de code suivant utilise toutes ces opérations.

API REST (Schéma) :

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]}}
    ]
}

Pour utiliser des points en lot avec un seul type d'opération, utilisez la fonctionnalité de lot directement dans cette opération.