Con iteradores
Milvus proporciona iteradores de búsqueda y consulta para iterar a través de un gran volumen de entidades. Dado que Milvus limita TopK a 16384, los usuarios pueden utilizar iteradores para devolver grandes números o incluso entidades enteras en una colección en modo por lotes.
Visión general
Los iteradores son una herramienta eficaz para escanear una colección completa o iterar a través de un gran volumen de entidades especificando valores de clave primaria o una expresión de filtro. En comparación con una llamada de búsqueda o consulta con parámetros de desplazamiento y límite, el uso de iteradores es más eficiente y escalable.
Ventajas del uso de iteradores
Simplicidad: Elimina los complejos parámetros de desplazamiento y límite.
Eficacia: Proporciona una recuperación de datos escalable al obtener sólo los datos necesarios.
Coherencia: Garantiza un tamaño coherente del conjunto de datos con filtros booleanos.
notas
- Esta función está disponible para Milvus 2.3.x o posterior.
Preparativos
El siguiente paso de preparación se conecta a Milvus e inserta entidades generadas aleatoriamente en una colección.
Paso 1: Crear una colección
Utilice MilvusClient
para conectarse al servidor Milvus y create_collection()
para crear una colección.
Utilice MilvusClientV2
para conectarse al servidor Milvus y createCollection()
para crear una colección.
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);
Paso 2: Insertar entidades generadas aleatoriamente
Utilice insert()
para insertar entidades en la colección.
Utilice insert()
para insertar entidades en la colección.
# 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
Búsqueda con iterador
Los iteradores hacen que las búsquedas por similitud sean más escalables.
Para buscar con un iterador, llama al método search_iterator():
Para buscar con un iterador, llame al método searchIterator():
Inicialice el iterador de búsqueda para definir los parámetros de búsqueda y los campos de salida.
Utilice el método next() dentro de un bucle para paginar los resultados de la búsqueda.
Si el método devuelve un array vacío, el bucle finaliza y no hay más páginas disponibles.
Todos los resultados llevan los campos de salida especificados.
Llame manualmente al método close() para cerrar el iterador una vez que se hayan recuperado todos los datos.
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 | Descripción |
---|---|
data |
Una lista de incrustaciones vectoriales. Milvus busca las incrustaciones vectoriales más similares a las especificadas. |
anns_field |
El nombre del campo vectorial en la colección actual. |
batch_size |
El número de entidades a devolver cada vez que se llama a next() en el iterador actual.El valor por defecto es 1000. Ajústelo a un valor adecuado para controlar el número de entidades a devolver por iteración. |
param |
Los parámetros específicos de esta operación.
|
output_fields |
Una lista de nombres de campo para incluir en cada entidad devuelta. El valor por defecto es None. Si no se especifica, sólo se incluye el campo principal. |
limit |
El número total de entidades que se devolverán. El valor predeterminado es -1, lo que indica que se devolverán todas las entidades coincidentes. |
Parámetro | Descripción |
---|---|
withCollectionName |
Establece el nombre de la colección. El nombre de la colección no puede estar vacío ni ser nulo. |
withVectorFieldName |
Establezca el nombre del campo del vector de destino. El nombre del campo no puede estar vacío ni ser nulo. |
withVectors |
Defina los vectores de destino. Se permiten hasta 16384 vectores. |
withBatchSize |
El número de entidades a devolver cada vez que se llama a next() en el iterador actual.El valor por defecto es 1000. Establézcalo a un valor apropiado para controlar el número de entidades a devolver por iteración. |
withParams |
Especifica los parámetros de búsqueda en formato JSON. Para más información, consulte searchIterator(). |
Consulta con un iterador
Para consultar con un iterador, llame al método query_iterator():
Para buscar con un iterador, llame al 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 | Descripción |
---|---|
batch_size |
El número de entidades a devolver cada vez que se llama a next() en el iterador actual.El valor por defecto es 1000. Establézcalo a un valor apropiado para controlar el número de entidades a devolver por iteración. |
expr |
Una condición de filtrado escalar para filtrar las entidades coincidentes. El valor predeterminado es None, lo que indica que se ignora el filtrado escalar. Para crear una condición de filtrado escalar, consulte Reglas de expresión booleana. |
output_fields |
Una lista de nombres de campo para incluir en cada entidad devuelta. El valor por defecto es Ninguno. Si no se especifica, sólo se incluye el campo principal. |
limit |
El número total de entidades que se devolverán. El valor predeterminado es -1, lo que indica que se devolverán todas las entidades coincidentes. |
Parámetro | Descripción |
---|---|
withCollectionName |
Establece el nombre de la colección. El nombre de la colección no puede estar vacío ni ser nulo. |
withExpr |
Establezca la expresión para consultar las entidades. Para crear una condición de filtrado escalar, consulte Reglas de expresión booleana. |
withBatchSize |
El número de entidades a devolver cada vez que se llama a next() en el iterador actual.El valor por defecto es 1000. Establézcalo a un valor apropiado para controlar el número de entidades a devolver por iteración. |
addOutField |
Especifica un campo escalar de salida (Opcional). |