Con gli iteratori
Milvus fornisce iteratori di ricerca e di interrogazione per iterare un grande volume di entità. Poiché Milvus limita TopK a 16384, gli utenti possono usare gli iteratori per restituire grandi numeri o addirittura intere entità in una collezione in modalità batch.
Panoramica
Gli iteratori sono uno strumento efficiente per la scansione di un'intera collezione o per l'iterazione di un grande volume di entità specificando i valori delle chiavi primarie o un'espressione di filtro. Rispetto a una chiamata di ricerca o di query con parametri di offset e limite, l'uso degli iteratori è più efficiente e scalabile.
Vantaggi dell'uso degli iteratori
Semplicità: Elimina le complesse impostazioni di offset e limite.
Efficienza: Fornisce un recupero scalabile dei dati, recuperando solo i dati necessari.
Coerenza: Assicura una dimensione coerente del set di dati con i filtri booleani.
note
- Questa funzione è disponibile per Milvus 2.3.x o successivo.
Preparazione
La seguente fase di preparazione si collega a Milvus e inserisce entità generate casualmente in una raccolta.
Passo 1: Creare una raccolta
Utilizzare MilvusClient
per connettersi al server Milvus e create_collection()
per creare una raccolta.
Utilizzare MilvusClientV2
per connettersi al server Milvus e createCollection()
per creare una raccolta.
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);
Passo 2: Inserire entità generate casualmente
Utilizzare insert()
per inserire le entità nell'insieme.
Utilizzare insert()
per inserire entità nell'insieme.
# 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
Ricerca con iteratore
Gli iteratori rendono le ricerche di similarità più scalabili.
Per cercare con un iteratore, chiamare il metodo search_iterator():
Per cercare con un iteratore, chiamare il metodo searchIterator():
Inizializzare l'iteratore di ricerca per definire i parametri di ricerca e i campi di output.
Utilizzare il metodo next() all'interno di un ciclo per scorrere i risultati della ricerca.
Se il metodo restituisce un array vuoto, il ciclo termina e non sono disponibili altre pagine.
Tutti i risultati contengono i campi di output specificati.
Chiamare manualmente il metodo close() per chiudere l'iteratore una volta recuperati tutti i dati.
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
Parametro | Descrizione |
---|---|
data |
Un elenco di incorporazioni vettoriali. Milvus cerca le incorporazioni vettoriali più simili a quelle specificate. |
anns_field |
Il nome del campo vettoriale nella collezione corrente. |
batch_size |
Il numero di entità da restituire ogni volta che si chiama next() sull'iteratore corrente.Il valore predefinito è 1000. Impostare un valore corretto per controllare il numero di entità da restituire per ogni iterazione. |
param |
Le impostazioni dei parametri specifiche per questa operazione.
|
output_fields |
Un elenco di nomi di campi da includere in ogni entità restituita. Il valore predefinito è Nessuno. Se non specificato, viene incluso solo il campo primario. |
limit |
Il numero totale di entità da restituire. Il valore predefinito è -1, a indicare che tutte le entità corrispondenti saranno restituite. |
Parametro | Descrizione |
---|---|
withCollectionName |
Imposta il nome della raccolta. Il nome della collezione non può essere vuoto o nullo. |
withVectorFieldName |
Impostare il nome del campo del vettore di destinazione. Il nome del campo non può essere vuoto o nullo. |
withVectors |
Impostare i vettori di destinazione. Sono ammessi fino a 16384 vettori. |
withBatchSize |
Il numero di entità da restituire ogni volta che si richiama next() sull'iteratore corrente.Il valore predefinito è 1000. Impostare un valore corretto per controllare il numero di entità da restituire per ogni iterazione. |
withParams |
Specifica i parametri della ricerca in formato JSON. Per ulteriori informazioni, consultare searchIterator(). |
Interrogazione con un iteratore
Per eseguire una query con un iteratore, chiamare il metodo query_iterator():
Per effettuare una ricerca con un iteratore, chiamare il metodo 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]
// ]
Parametro | Descrizione |
---|---|
batch_size |
Il numero di entità da restituire ogni volta che si chiama next() sull'iteratore corrente.Il valore predefinito è 1000. Impostare un valore corretto per controllare il numero di entità da restituire per iterazione. |
expr |
Una condizione di filtraggio scalare per filtrare le entità corrispondenti. Il valore predefinito è None, a indicare che il filtraggio scalare è ignorato. Per creare una condizione di filtraggio scalare, fare riferimento a Regole di espressione booleana. |
output_fields |
Un elenco di nomi di campi da includere in ogni entità di ritorno. Il valore predefinito è Nessuno. Se non viene specificato, viene incluso solo il campo primario. |
limit |
Il numero totale di entità da restituire. Il valore predefinito è -1, a indicare che tutte le entità corrispondenti saranno restituite. |
Parametro | Descrizione |
---|---|
withCollectionName |
Imposta il nome della raccolta. Il nome della collezione non può essere vuoto o nullo. |
withExpr |
Impostare l'espressione per interrogare le entità. Per creare una condizione di filtraggio scalare, fare riferimento a Regole di espressione booleana. |
withBatchSize |
Il numero di entità da restituire ogni volta che si richiama next() sull'iteratore corrente.Il valore predefinito è 1000. Impostare un valore corretto per controllare il numero di entità da restituire per ogni iterazione. |
addOutField |
Specifica un campo scalare di uscita (facoltativo). |