milvus-logo
LFAI
Casa
  • Guida per l'utente

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():

  1. Inizializzare l'iteratore di ricerca per definire i parametri di ricerca e i campi di output.

  2. 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.

  3. 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.
  • metric_type: Il tipo di metrica applicata a questa operazione. Deve essere lo stesso utilizzato quando si indicizza il campo vettoriale specificato sopra. I valori possibili sono L2, IP, COSINE, JACCARD, HAMMING.
  • params: Parametri aggiuntivi. Per i dettagli, fare riferimento a search_iterator().
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).

Tradotto daDeepLogo

Try Managed Milvus for Free

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

Get Started
Feedback

Questa pagina è stata utile?