milvus-logo
LFAI
Home
  • Guia do utilizador

Com Iteradores

O Milvus fornece iteradores de pesquisa e consulta para iterar resultados com um grande volume de entidades. Uma vez que o Milvus limita o TopK a 16384, os utilizadores podem utilizar iteradores para devolver grandes números ou mesmo entidades inteiras numa coleção em modo batch.

Visão geral

Os iteradores são ferramentas poderosas que ajudam a iterar através de um grande volume de dados ou de todos os dados de uma coleção, utilizando valores de chave primária e expressões booleanas. Isto pode melhorar significativamente a forma como recupera os dados. Ao contrário da utilização tradicional de parâmetros de desvio e limite, que podem tornar-se menos eficientes ao longo do tempo, os iteradores oferecem uma solução mais escalável.

Vantagens da utilização de iteradores

  • Simplicidade: Elimina as complexas definições de desvio e limite.

  • Eficiência: Fornece recuperação de dados escalável, buscando apenas os dados necessários.

  • Consistência: Garante um tamanho de conjunto de dados consistente com filtros booleanos.

notas

  • Esta funcionalidade está disponível para o Milvus 2.3.x ou posterior.

Preparações

As etapas a seguir redirecionam o código para se conectar ao Milvus, configurar rapidamente uma coleção e inserir mais de 10.000 entidades geradas aleatoriamente na coleção.

Passo 1: Criar uma coleção

Utilize MilvusClient para se ligar ao servidor Milvus e create_collection() para criar uma coleção.

Utilize MilvusClientV2 para se ligar ao servidor Milvus e createCollection() para criar uma coleção.

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);

Passo 2: Inserir entidades geradas aleatoriamente

Utilize insert() para inserir entidades na coleção.

Utilizar insert() para inserir entidades na coleção.

# 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());

Pesquisa com iterador

Os iteradores tornam as pesquisas por semelhança mais escaláveis.

Para pesquisar com um iterador, chame o método search_iterator():

Para pesquisar com um iterador, chame o método searchIterator():

  1. Inicialize o iterador de pesquisa para definir os parâmetros de pesquisa e os campos de saída.

  2. Utilize o método next() dentro de um loop para paginar os resultados da pesquisa.

    • Se o método retornar uma matriz vazia, o loop termina e não há mais páginas disponíveis.

    • Todos os resultados contêm os campos de saída especificados.

  3. Chame manualmente o método close() para fechar o iterador quando todos os dados tiverem sido recuperados.

from pymilvus import Collection

# 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=3
)

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());
Parâmetro Descrição
data Uma lista de incorporações vectoriais.
Milvus procura as incorporações vectoriais mais semelhantes às especificadas.
anns_field O nome do campo vetorial na coleção atual.
batch_size O número de entidades a devolver sempre que chamar next() no iterador atual.
O valor predefinido é 1000. Defina-o para um valor adequado para controlar o número de entidades a retornar por iteração.
param As definições dos parâmetros específicos desta operação.
  • metric_type: O tipo de métrica aplicado a esta operação. Este deve ser o mesmo que o utilizado quando indexa o campo vetorial especificado acima. Os valores possíveis são L2, IP, COSINE, JACCARD, HAMMING.
  • params: Parâmetros adicionais. Para obter detalhes, consulte search_iterator().
output_fields Uma lista de nomes de campo para incluir em cada entidade em retorno.
O valor padrão é None. Se não for especificado, apenas o campo primário será incluído.
limit O número total de entidades a serem retornadas.
O valor padrão é -1, indicando que todas as entidades correspondentes serão retornadas.
Parâmetro Descrição
withCollectionName Define o nome da coleção. O nome da coleção não pode estar vazio ou ser nulo.
withVectorFieldName Definir o campo do vetor de destino por nome. O nome do campo não pode estar vazio ou ser nulo.
withVectors Definir os vectores de destino. São permitidos até 16384 vectores.
withBatchSize O número de entidades a retornar cada vez que você chamar next() no iterador atual.
O valor padrão é 1000. Defina-o para um valor adequado para controlar o número de entidades a devolver por iteração.
withParams Especifica os parâmetros de pesquisa no formato JSON. Para obter mais informações, consulte searchIterator().

Consultar com um iterador

Para consultar com um iterador, chame o método query_iterator():

Para pesquisar com um iterador, chame o método 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();
    }
}
Parâmetro Descrição
batch_size O número de entidades a devolver sempre que chamar next() no iterador atual.
O valor predefinido é 1000. Defina-o para um valor adequado para controlar o número de entidades a devolver por iteração.
expr Uma condição de filtragem escalar para filtrar entidades correspondentes.
O valor padrão é Nenhum, indicando que a filtragem escalar é ignorada. Para criar uma condição de filtragem escalar, consulte Regras de expressão booleana.
output_fields Uma lista de nomes de campo para incluir em cada entidade em retorno.
O valor padrão é None. Se não for especificado, apenas o campo primário será incluído.
limit O número total de entidades a devolver.
O valor predefinido é -1, indicando que todas as entidades correspondentes serão devolvidas.
Parâmetro Descrição
withCollectionName Define o nome da coleção. O nome da coleção não pode estar vazio ou ser nulo.
withExpr Define a expressão para consultar entidades. Para criar uma condição de filtragem escalar, consulte Regras de expressão booleana.
withBatchSize O número de entidades a retornar cada vez que você chamar next() no iterador atual.
O valor padrão é 1000. Defina-o para um valor adequado para controlar o número de entidades a serem retornadas por iteração.
addOutField Especifica um campo escalar de saída (opcional).

Traduzido porDeepLogo

Try Zilliz Cloud for Free

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

Get Started
Feedback

Esta página foi útil?