Such-Iterator

Die ANN-Suche unterliegt einer Obergrenze für die Anzahl der Entitäten, die bei einer einzelnen Abfrage abgerufen werden können, und die einfache Verwendung der grundlegenden ANN-Suche reicht möglicherweise nicht aus, um die Anforderungen einer groß angelegten Abfrage zu erfüllen. Bei ANN-Suchanfragen, bei denen „topK“ den Wert 16.384 überschreitet, empfiehlt es sich, den Einsatz des SearchIterators in Betracht zu ziehen. In diesem Abschnitt werden die Verwendung des SearchIterators und damit verbundene Überlegungen vorgestellt.

Übersicht

Eine Suchanfrage liefert Suchergebnisse zurück, während ein „SearchIterator“ einen Iterator zurückgibt. Sie können die Methode „next()“ dieses Iterators aufrufen, um die Suchergebnisse abzurufen.

Konkret können Sie den „SearchIterator“ wie folgt verwenden:

  1. Erstellen Sie einen SearchIterator und legen Sie die Anzahl der pro Suchanfrage zurückzugebenden Entitäten sowie die Gesamtzahl der zurückzugebenden Entitäten fest.

  2. Rufen Sie die Methode `next()` des `SearchIterator` in einer Schleife auf, um die Suchergebnisse paginiert abzurufen.

  3. Rufen Sie die Methode „close()“ des Iterators auf, um die Schleife zu beenden, wenn die Methode „next()“ ein leeres Ergebnis zurückgibt.

SearchIterator erstellen

Der folgende Codeausschnitt veranschaulicht, wie ein SearchIterator erstellt wird.

from pymilvus import connections, Collection

connections.connect(
    uri="http://localhost:19530",
    token="root:Milvus"
)

# create iterator
query_vectors = [
    [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]]

collection = Collection("iterator_collection")

iterator = collection.search_iterator(
    data=query_vectors,
    anns_field="vector",
    param={"metric_type": "L2", "params": {"nprobe": 16}},
    batch_size=50,
    output_fields=["color"],
    limit=20000
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.orm.iterator.SearchIterator;
import io.milvus.v2.common.IndexParam.MetricType;
import io.milvus.v2.service.vector.request.data.FloatVec;

import java.util.*;

MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
        .uri("http://localhost:19530")
        .token("root:Milvus")
        .build());

FloatVec queryVector = new FloatVec(new float[]{0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f});
SearchIterator searchIterator = client.searchIterator(SearchIteratorReq.builder()
        .collectionName("iterator_collection")
        .vectors(Collections.singletonList(queryVector))
        .vectorFieldName("vector")
        .batchSize(500L)
        .outputFields(Lists.newArrayList("color"))
        .topK(20000)
        .metricType(IndexParam.MetricType.COSINE)
        .build());
// go
import { MilvusClient } from '@zilliz/milvus2-sdk-node';

const milvusClient = new MilvusClient({
  address: 'http://localhost:19530',
  token: 'root:Milvus',
});

const queryVectors = [
[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592],
];
const collectionName = 'iterator_collection';

const iterator = milvusClient.searchIterator({
    collection_name: collectionName,
    vectors: queryVectors,
    anns_field: 'vector',
    params: { metric_type: 'L2', params: { nprobe: 16 } },
    batch_size: 50,
    output_fields: ['color'],
    limit: 20000,
});

export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d '{
    "collectionName": "iterator_collection",
    "annsField": "vector",
    "data": [[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]],
    "searchParams": {
        "metricType": "L2",
        "params": {
            "nprobe": 16
        }
    },
    "limit": 50,
    "offset": 0,
    "outputFields": ["color"]
}'
#include <iostream>
#include <vector>

#include "milvus/MilvusClientV2.h"

auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("http://localhost:19530", "root:Milvus"));
if (!status.IsOk()) {
    std::cerr << "Failed to connect: " << status.Message() << std::endl;
    return;
}

// create iterator
std::vector<float> queryVector = {
    0.35803764F, -0.60234958F, 0.18414013F, -0.26286206F, 0.90294385F
};

milvus::SearchIteratorRequest request;
request.SetCollectionName("iterator_collection");
request.SetAnnsField("vector");
request.SetMetricType(milvus::MetricType::L2);
request.AddExtraParam("nprobe", "16");
request.SetBatchSize(50);
request.AddOutputField("color");
request.SetLimit(20000);
// SearchIterator only accepts one vector
request.AddFloatVector(queryVector);

milvus::SearchIteratorPtr iterator;
status = client->SearchIterator(request, iterator);
if (!status.IsOk()) {
    std::cerr << "Failed to create search iterator: " << status.Message() << std::endl;
    return;
}

In den obigen Beispielen haben Sie die Anzahl der pro Suche zurückzugebenden Entitäten (batch_size/batchSize) auf 50 und die Gesamtzahl der zurückzugebenden Entitäten (topK) auf 20.000 festgelegt.

SearchIterator verwenden

Sobald der SearchIterator bereit ist, können Sie dessen next()-Methode aufrufen, um die Suchergebnisse paginiert abzurufen.

results = []

while True:
    result = iterator.next()
    if not result:
        iterator.close()
        break
    
    for hit in result:
        results.append(hit.to_dict())
import io.milvus.response.QueryResultsWrapper;

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

    for (QueryResultsWrapper.RowRecord record : res) {
        System.out.println(record);
    }
}
// go
for await (const result of iterator) {
    console.log(result);
}
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"

batch_size=50
limit=20000
offset=0

# Paginate with offset until an empty page is returned. Note that the sum of
# offset and limit in each request must not exceed the server-side result
# window (16,384 by default); SDK search iterators do not have this limit.
while [ "$offset" -lt "$limit" ]; do
    response=$(curl --silent --request POST \
        --url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
        --header "Authorization: Bearer ${TOKEN}" \
        --header "Content-Type: application/json" \
        --header "Request-Timeout: 10" \
        -d '{
            "collectionName": "iterator_collection",
            "annsField": "vector",
            "data": [[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]],
            "searchParams": {
                "metricType": "L2",
                "params": {
                    "nprobe": 16
                }
            },
            "limit": '"$batch_size"',
            "offset": '"$offset"',
            "outputFields": ["color"]
        }')

    count=$(echo "$response" | jq -r '.data | length')
    if [ "$count" -eq 0 ]; then
        break
    fi

    echo "$response" | jq -r '.data[]'
    offset=$((offset + batch_size))
done
while (true) {
    milvus::SingleResult result;
    status = iterator->Next(result);
    if (!status.IsOk()) {
        std::cerr << "Iterator next failed: " << status.Message() << std::endl;
        break;
    }
    if (result.GetRowCount() == 0) {
        break;
    }

    milvus::EntityRows rows;
    status = result.OutputRows(rows);
    if (!status.IsOk()) {
        std::cerr << "Failed to get output rows: " << status.Message() << std::endl;
        break;
    }

    for (const auto& row : rows) {
        std::cout << row.dump() << std::endl;
    }
}

In den obigen Code-Beispielen haben Sie eine Endlosschleife erstellt und innerhalb der Schleife die Methode `next()` aufgerufen, um die Suchergebnisse in einer Variablen zu speichern. Sobald ` next()` nichts mehr zurückgibt, haben Sie den Iterator geschlossen.

Übersetzt vonDeepL

Verwaltetes Milvus kostenlos testen

Zilliz Cloud ist unkompliziert, basiert auf Milvus und ist 10-mal schneller.

Loslegen
Feedback

War diese Seite hilfreich?