milvus-logo
LFAI
Home
  • Guide de l'utilisateur

Avec les itérateurs

Milvus fournit des itérateurs de recherche et de requête pour parcourir un grand volume d'entités. Milvus limitant TopK à 16384, les utilisateurs peuvent utiliser les itérateurs pour renvoyer de grands nombres ou même des entités entières dans une collection en mode batch.

Vue d'ensemble

Les itérateurs sont des outils efficaces pour analyser une collection entière ou parcourir un grand volume d'entités en spécifiant des valeurs de clé primaire ou une expression de filtre. Par rapport à un appel de recherche ou de requête avec des paramètres de décalage et de limite, l'utilisation d'itérateurs est plus efficace et plus évolutive.

Avantages de l'utilisation d'itérateurs

  • Simplicité: Élimine les paramètres complexes de décalage et de limite.

  • Efficacité: Permet une extraction évolutive des données en ne récupérant que les données nécessaires.

  • Cohérence: Garantit une taille cohérente des ensembles de données grâce aux filtres booléens.

notes

  • Cette fonctionnalité est disponible pour Milvus 2.3.x ou plus récent.

Préparations

L'étape de préparation suivante se connecte à Milvus et insère des entités générées de manière aléatoire dans une collection.

Étape 1 : Création d'une collection

Utilisez MilvusClient pour se connecter au serveur Milvus et create_collection() pour créer une collection.

Pour se connecter au serveur Milvus et créer une collection, il faut utiliser MilvusClientV2 pour se connecter au serveur Milvus et createCollection() pour créer une collection.

from pymilvus import MilvusClient

# 1. Set up a Milvus client
client = MilvusClient(
    uri="http://localhost:19530"
)

# 2. Create a collection
client.create_collection(
    collection_name="quick_setup",
    dimension=5,
)
import io.milvus.client.MilvusServiceClient;
import io.milvus.param.ConnectParam;
import io.milvus.param.highlevel.collection.CreateSimpleCollectionParam;

String CLUSTER_ENDPOINT = "http://localhost:19530";

// 1. Connect to Milvus server
ConnectParam connectParam = ConnectParam.newBuilder()
        .withUri(CLUSTER_ENDPOINT)
        .build();

MilvusServiceClient client  = new MilvusServiceClient(connectParam);

// 2. Create a collection
CreateSimpleCollectionParam createCollectionParam = CreateSimpleCollectionParam.newBuilder()
        .withCollectionName("quick_setup")
        .withDimension(5)
        .build();

client.createCollection(createCollectionParam);

Étape 2 : Insérer des entités générées aléatoirement

Utilisez insert() pour insérer des entités dans la collection.

Utiliser insert() pour insérer des entités dans la collection.

# 3. Insert randomly generated vectors 
colors = ["green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey"]
data = []

for i in range(10000):
    current_color = random.choice(colors)
    current_tag = random.randint(1000, 9999)
    data.append({
        "id": i,
        "vector": [ random.uniform(-1, 1) for _ in range(5) ],
        "color": current_color,
        "tag": current_tag,
        "color_tag": f"{current_color}_{str(current_tag)}"
    })

print(data[0])

# Output
#
# {
#     "id": 0,
#     "vector": [
#         -0.5705990742218152,
#         0.39844925120642083,
#         -0.8791287928610869,
#         0.024163154953680932,
#         0.6837669917169638
#     ],
#     "color": "purple",
#     "tag": 7774,
#     "color_tag": "purple_7774"
# }

res = client.insert(
    collection_name="quick_setup",
    data=data,
)

print(res)

# Output
#
# {
#     "insert_count": 10000,
#     "ids": [
#         0,
#         1,
#         2,
#         3,
#         4,
#         5,
#         6,
#         7,
#         8,
#         9,
#         "(9990 more items hidden)"
#     ]
# }
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

import com.alibaba.fastjson.JSONObject;

import io.milvus.param.R;
import io.milvus.param.dml.InsertParam;
import io.milvus.response.MutationResultWrapper;
import io.milvus.grpc.MutationResult;


// 3. Insert randomly generated vectors into the collection
List<String> colors = Arrays.asList("green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey");
List<JSONObject> data = new ArrayList<>();

for (int i=0; i<10000; i++) {
    Random rand = new Random();
    String current_color = colors.get(rand.nextInt(colors.size()-1));
    JSONObject row = new JSONObject();
    row.put("id", Long.valueOf(i));
    row.put("vector", Arrays.asList(rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat()));
    row.put("color_tag", current_color + "_" + String.valueOf(rand.nextInt(8999) + 1000));
    data.add(row);
}

InsertParam insertParam = InsertParam.newBuilder()
    .withCollectionName("quick_setup")
    .withRows(data)
    .build();

R<MutationResult> insertRes = client.insert(insertParam);

if (insertRes.getStatus() != R.Status.Success.getCode()) {
    System.err.println(insertRes.getMessage());
}

MutationResultWrapper wrapper = new MutationResultWrapper(insertRes.getData());
System.out.println(wrapper.getInsertCount());

Recherche avec itérateur

Les itérateurs rendent les recherches de similarité plus évolutives.

Pour effectuer une recherche avec un itérateur, appelez la méthode search_iterator():

Pour effectuer une recherche avec un itérateur, appelez la méthode searchIterator():

  1. Initialiser l'itérateur de recherche pour définir les paramètres de recherche et les champs de sortie.

  2. Utilisez la méthode next() dans une boucle pour faire défiler les résultats de la recherche.

    • Si la méthode renvoie un tableau vide, la boucle se termine et aucune autre page n'est disponible.

    • Tous les résultats contiennent les champs de sortie spécifiés.

  3. Appelez manuellement la méthode close() pour fermer l'itérateur une fois que toutes les données ont été récupérées.

from pymilvus import Collection,connections

# 4. Search with iterator
connections.connect(host="127.0.0.1", port=19530)
collection = Collection("quick_setup")

query_vectors = [[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]]
search_params = {
    "metric_type": "IP",
    "params": {"nprobe": 10}
}

iterator = collection.search_iterator(
    data=query_vectors,
    anns_field="vector",
    batch_size=10,
    param=search_params,
    output_fields=["color_tag"],
    limit=300
)
# search 300 entities totally with 10 entities per page

results = []

while True:
    result = iterator.next()
    if not result:
        iterator.close()
        break
        
    results.extend(result)
    
    for hit in result:
        results.append(hit.to_dict())

print(results)

# Output
#
# [
#     {
#         "id": 1756,
#         "distance": 2.0642056465148926,
#         "entity": {
#             "color_tag": "black_9109"
#         }
#     },
#     {
#         "id": 6488,
#         "distance": 1.9437453746795654,
#         "entity": {
#             "color_tag": "purple_8164"
#         }
#     },
#     {
#         "id": 3338,
#         "distance": 1.9107104539871216,
#         "entity": {
#             "color_tag": "brown_8121"
#         }
#     }
# ]
import io.milvus.param.dml.QueryIteratorParam;
import io.milvus.param.dml.SearchIteratorParam;
import io.milvus.response.QueryResultsWrapper;
import io.milvus.orm.iterator.SearchIterator;

// 4. Search with iterators
SearchIteratorParam iteratorParam = SearchIteratorParam.newBuilder()
    .withCollectionName("quick_setup")
    .withVectorFieldName("vector")
    // Use withFloatVectors() in clusters compatible with Milvus 2.4.x
    .withVectors(Arrays.asList(0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f))
    .withBatchSize(10L)
    .withParams("{\"metric_type\": \"COSINE\", \"params\": {\"level\": 1}}")
    .build();
        

R<SearchIterator> searchIteratorRes = client.searchIterator(iteratorParam);

if (searchIteratorRes.getStatus() != R.Status.Success.getCode()) {
    System.err.println(searchIteratorRes.getMessage());
}

SearchIterator searchIterator = searchIteratorRes.getData();
List<QueryResultsWrapper.RowRecord> results = new ArrayList<>();

while (true) {
    List<QueryResultsWrapper.RowRecord> batchResults = searchIterator.next();
    if (batchResults.isEmpty()) {
        searchIterator.close();
        break;
    }
    for (QueryResultsWrapper.RowRecord rowRecord : batchResults) {
        results.add(rowRecord);
    }
}

System.out.println(results.size());
Paramètre Description
data Une liste d'intégrations vectorielles.
Milvus recherche les intégrations vectorielles les plus similaires à celles spécifiées.
anns_field Le nom du champ vectoriel dans la collection actuelle.
batch_size Le nombre d'entités à renvoyer chaque fois que vous appelez next() sur l'itérateur actuel.
La valeur par défaut est 1000. Définissez-la à une valeur appropriée pour contrôler le nombre d'entités à renvoyer par itération.
param Les paramètres spécifiques à cette opération.
  • metric_type: Le type de métrique appliqué à cette opération. Il doit être identique à celui utilisé lors de l'indexation du champ vectoriel spécifié ci-dessus. Les valeurs possibles sont L2, IP, COSINE, JACCARD, HAMMING.
  • params: Paramètres supplémentaires. Pour plus de détails, voir search_iterator().
output_fields Une liste de noms de champs à inclure dans chaque entité en retour.
La valeur par défaut est None. Si elle n'est pas spécifiée, seul le champ primaire est inclus.
limit Le nombre total d'entités à renvoyer.
La valeur par défaut est -1, ce qui indique que toutes les entités correspondantes seront renvoyées.
Paramètre Description de la collection
withCollectionName Définit le nom de la collection. Le nom de la collection ne peut pas être vide ou nul.
withVectorFieldName Définit le nom du champ vectoriel cible. Le nom du champ ne peut être vide ou nul.
withVectors Définir les vecteurs cibles. Un maximum de 16384 vecteurs est autorisé.
withBatchSize Nombre d'entités à renvoyer chaque fois que vous appelez next() sur l'itérateur actuel.
La valeur par défaut est 1000. Définissez-la à une valeur appropriée pour contrôler le nombre d'entités à renvoyer par itération.
withParams Spécifie les paramètres de la recherche au format JSON. Pour plus d'informations, voir searchIterator().

Interroger avec un itérateur

Pour effectuer une requête avec un itérateur, appelez la méthode query_iterator():

Pour effectuer une recherche avec un itérateur, appelez la méthode queryIterator():

# 6. Query with iterator
iterator = collection.query_iterator(
    batch_size=10, # Controls the size of the return each time you call next()
    expr="color_tag like \"brown_8\"",
    output_fields=["color_tag"]
)

results = []

while True:
    result = iterator.next()
    if not result:
        iterator.close()
        break
        
    results.extend(result)
    
# 8. Check the search results
print(len(results))

print(results[:3])

# Output
#
# [
#     {
#         "color_tag": "brown_8785",
#         "id": 94
#     },
#     {
#         "color_tag": "brown_8568",
#         "id": 176
#     },
#     {
#         "color_tag": "brown_8721",
#         "id": 289
#     }
# ]
import io.milvus.param.dml.QueryIteratorParam;
import io.milvus.orm.iterator.QueryIterator;

// 5. Query with iterators

try {
    Files.write(Path.of("results.json"), JSON.toJSONString(new ArrayList<>()).getBytes(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
} catch (Exception e) {
    // TODO: handle exception
    e.printStackTrace();
}

QueryIteratorParam queryIteratorParam = QueryIteratorParam.newBuilder()
    .withCollectionName("quick_setup")
    .withExpr("color_tag like \"brown_8%\"")
    .withBatchSize(50L)
    .addOutField("vector")
    .addOutField("color_tag")
    .build();

R<QueryIterator> queryIteratRes = client.queryIterator(queryIteratorParam);

if (queryIteratRes.getStatus() != R.Status.Success.getCode()) {
    System.err.println(queryIteratRes.getMessage());
}

QueryIterator queryIterator = queryIteratRes.getData();

while (true) {
    List<QueryResultsWrapper.RowRecord> batchResults = queryIterator.next();
    if (batchResults.isEmpty()) {
        queryIterator.close();
        break;
    }

    String jsonString = "";
    List<JSONObject> jsonObject = new ArrayList<>();
    try {
        jsonString = Files.readString(Path.of("results.json"));
        jsonObject = JSON.parseArray(jsonString).toJavaList(null);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    for (QueryResultsWrapper.RowRecord queryResult : batchResults) {
        JSONObject row = new JSONObject();
        row.put("id", queryResult.get("id"));
        row.put("vector", queryResult.get("vector"));
        row.put("color_tag", queryResult.get("color_tag"));
        jsonObject.add(row);
    }

    try {
        Files.write(Path.of("results.json"), JSON.toJSONString(jsonObject).getBytes(), StandardOpenOption.WRITE);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
Paramètre Description
batch_size Le nombre d'entités à renvoyer chaque fois que vous appelez next() sur l'itérateur actuel.
La valeur par défaut est de 1000. Définissez-la à une valeur appropriée pour contrôler le nombre d'entités à renvoyer par itération.
expr Une condition de filtrage scalaire pour filtrer les entités correspondantes.
La valeur par défaut est None, ce qui indique que le filtrage scalaire est ignoré. Pour créer une condition de filtrage scalaire, reportez-vous à la section Règles d'expression booléenne.
output_fields Une liste de noms de champs à inclure dans chaque entité en retour.
La valeur par défaut est None. Si elle n'est pas spécifiée, seul le champ primaire est inclus.
limit Le nombre total d'entités à renvoyer.
La valeur par défaut est -1, ce qui indique que toutes les entités correspondantes seront renvoyées.
Paramètre Description de la collection
withCollectionName Définit le nom de la collection. Le nom de la collection ne peut pas être vide ou nul.
withExpr Définit l'expression pour interroger les entités. Pour créer une condition de filtrage scalaire, reportez-vous à la section Règles des expressions booléennes.
withBatchSize Nombre d'entités à renvoyer chaque fois que vous appelez next() sur l'itérateur actuel.
La valeur par défaut est 1000. Définissez-la à une valeur appropriée pour contrôler le nombre d'entités à renvoyer par itération.
addOutField Spécifie un champ scalaire de sortie (Facultatif).

Traduit parDeepLogo

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started
Feedback

Cette page a-t - elle été utile ?