Com Iteradores
Milvus fornece iteradores de pesquisa e consulta para iterar através de 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 uma ferramenta eficiente para pesquisar uma coleção inteira ou iterar através de um grande volume de entidades, especificando valores de chave primária ou uma expressão de filtro. Em comparação com uma chamada de pesquisa ou consulta com parâmetros de deslocamento e limite, a utilização de iteradores é mais eficiente e escalável.
Vantagens da utilização de iteradores
Simplicidade: Elimina as complexas definições de offset e limite.
Eficiência: Fornece recuperação escalável de dados, 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
O seguinte passo de preparação liga-se ao Milvus e insere entidades geradas aleatoriamente numa coleção.
Passo 1: Criar uma coleção
Use 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 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: 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)"
# ]
# }
// 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
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():
Inicialize o iterador de pesquisa para definir os parâmetros de pesquisa e os campos de saída.
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.
Chame manualmente o método close() para fechar o iterador quando todos os dados tiverem sido recuperados.
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
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.
|
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
# }
# ]
// 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]
// ]
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). |