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 com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.milvus.orm.iterator.QueryIterator;
import io.milvus.orm.iterator.SearchIterator;
import io.milvus.response.QueryResultsWrapper;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.common.ConsistencyLevel;
import io.milvus.v2.common.IndexParam;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
import io.milvus.v2.service.collection.request.DropCollectionReq;
import io.milvus.v2.service.vector.request.*;
import io.milvus.v2.service.vector.request.data.FloatVec;
import io.milvus.v2.service.vector.response.InsertResp;
import io.milvus.v2.service.vector.response.QueryResp;
import java.util.*;
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
CreateCollectionReq quickSetupReq = CreateCollectionReq.builder()
.collectionName("quick_setup")
.dimension(5)
.build();
client.createCollection(quickSetupReq);
É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)"
# ]
# }
// 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<>();
Gson gson = new Gson();
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.addProperty("id", (long) i);
row.add("vector", gson.toJsonTree(Arrays.asList(rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat(), rand.nextFloat())));
row.addProperty("color_tag", current_color + "_" + (rand.nextInt(8999) + 1000));
data.add(row);
}
InsertResp insertR = client.insert(InsertReq.builder()
.collectionName("quick_setup")
.data(data)
.build());
System.out.println(insertR.getInsertCnt());
// Output
// 10000
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():
Initialiser l'itérateur de recherche pour définir les paramètres de recherche et les champs de sortie.
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.
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"
# }
# }
# ]
// 4. Search with iterators
SearchIteratorReq iteratorReq = SearchIteratorReq.builder()
.collectionName("quick_setup")
.vectorFieldName("vector")
.batchSize(10L)
.vectors(Collections.singletonList(new FloatVec(Arrays.asList(0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f))))
.params("{\"level\": 1}")
.metricType(IndexParam.MetricType.COSINE)
.outputFields(Collections.singletonList("color_tag"))
.topK(300)
.build();
SearchIterator searchIterator = client.searchIterator(iteratorReq);
List<QueryResultsWrapper.RowRecord> results = new ArrayList<>();
while (true) {
List<QueryResultsWrapper.RowRecord> batchResults = searchIterator.next();
if (batchResults.isEmpty()) {
searchIterator.close();
break;
}
results.addAll(batchResults);
}
System.out.println(results.size());
// Output
// 300
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.
|
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
# }
# ]
// 5. Query with iterators
QueryIterator queryIterator = client.queryIterator(QueryIteratorReq.builder()
.collectionName("quick_setup")
.expr("color_tag like \"brown_8%\"")
.batchSize(50L)
.outputFields(Arrays.asList("vector", "color_tag"))
.build());
results.clear();
while (true) {
List<QueryResultsWrapper.RowRecord> batchResults = queryIterator.next();
if (batchResults.isEmpty()) {
queryIterator.close();
break;
}
results.addAll(batchResults);
}
System.out.println(results.subList(0, 3));
// Output
// [
// [color_tag:brown_8975, vector:[0.93425006, 0.42161798, 0.1603949, 0.86406225, 0.30063087], id:104],
// [color_tag:brown_8292, vector:[0.075261295, 0.51725155, 0.13842249, 0.13178307, 0.90713704], id:793],
// [color_tag:brown_8763, vector:[0.80366623, 0.6534371, 0.6446101, 0.094082, 0.1318503], id:1157]
// ]
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). |