Mit Iteratoren
Milvus bietet Such- und Abfrage-Iteratoren für die Iteration durch ein großes Volumen von Entitäten. Da Milvus TopK auf 16384 begrenzt, können Benutzer Iteratoren verwenden, um große Zahlen oder sogar ganze Entitäten in einer Sammlung im Batch-Modus zurückzugeben.
Überblick
Iteratoren sind ein effizientes Werkzeug zum Scannen einer ganzen Sammlung oder zum Iterieren durch eine große Menge von Entitäten durch Angabe von Primärschlüsselwerten oder eines Filterausdrucks. Im Vergleich zu einem Such- oder Abfrageaufruf mit Offset- und Limit-Parametern ist die Verwendung von Iteratoren effizienter und skalierbarer.
Vorteile der Verwendung von Iteratoren
Vereinfachung: Die komplexen Offset- und Limit-Einstellungen entfallen.
Effizient: Ermöglicht einen skalierbaren Datenabruf, indem nur die benötigten Daten abgerufen werden.
Konsistenz: Gewährleistet eine konsistente Datensatzgröße mit booleschen Filtern.
Hinweise
- Diese Funktion ist für Milvus 2.3.x oder höher verfügbar.
Vorbereitungen
Der folgende Vorbereitungsschritt stellt eine Verbindung zu Milvus her und fügt zufällig generierte Entitäten in eine Sammlung ein.
Schritt 1: Erstellen einer Sammlung
Verwenden Sie MilvusClient
um sich mit dem Milvus-Server zu verbinden und create_collection()
um eine Sammlung zu erstellen.
Verwenden Sie MilvusClientV2
um eine Verbindung zum Milvus-Server herzustellen und createCollection()
um eine Sammlung zu erstellen.
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);
Schritt 2: Zufällig generierte Entitäten einfügen
Verwenden Sie insert()
um Entitäten in die Sammlung einzufügen.
Verwenden Sie insert()
um Entitäten in die Sammlung einzufügen.
# 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
Suche mit Iterator
Iteratoren machen Ähnlichkeitssuchen besser skalierbar.
Um mit einem Iterator zu suchen, rufen Sie die Methode search_iterator() auf:
Um mit einem Iterator zu suchen, rufen Sie die Methode searchIterator() auf:
Initialisieren Sie den Such-Iterator, um die Suchparameter und Ausgabefelder zu definieren.
Verwenden Sie die next() -Methode innerhalb einer Schleife, um durch die Suchergebnisse zu paginieren.
Wenn die Methode ein leeres Array zurückgibt, endet die Schleife, und es sind keine weiteren Seiten verfügbar.
Alle Ergebnisse enthalten die angegebenen Ausgabefelder.
Rufen Sie manuell die Methode close() auf, um den Iterator zu schließen, sobald alle Daten abgerufen wurden.
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
Parameter | Beschreibung |
---|---|
data |
Eine Liste von Vektoreinbettungen. Milvus sucht nach den Vektoreinbettungen, die den angegebenen am ähnlichsten sind. |
anns_field |
Der Name des Vektorfeldes in der aktuellen Sammlung. |
batch_size |
Die Anzahl der Entitäten, die jedes Mal zurückgegeben werden sollen, wenn Sie next() für den aktuellen Iterator aufrufen.Der Wert ist standardmäßig 1000. Setzen Sie ihn auf einen geeigneten Wert, um die Anzahl der pro Iteration zurückzugebenden Objekte zu steuern. |
param |
Die spezifischen Parametereinstellungen für diese Operation.
|
output_fields |
Eine Liste von Feldnamen, die in jeder zurückgegebenen Entität enthalten sein sollen. Der Standardwert ist None. Wenn er nicht angegeben wird, wird nur das Primärfeld einbezogen. |
limit |
Die Gesamtzahl der zurückzugebenden Entitäten. Der Standardwert ist -1, was bedeutet, dass alle passenden Entitäten zurückgegeben werden. |
Parameter | Beschreibung |
---|---|
withCollectionName |
Legt den Namen der Sammlung fest. Der Sammlungsname darf nicht leer oder null sein. |
withVectorFieldName |
Zielvektorfeld nach Name festlegen. Der Feldname darf nicht leer oder ungültig sein. |
withVectors |
Legen Sie die Zielvektoren fest. Bis zu 16384 Vektoren sind zulässig. |
withBatchSize |
Die Anzahl der Entitäten, die bei jedem Aufruf von next() für den aktuellen Iterator zurückgegeben werden.Der Standardwert ist 1000. Setzen Sie ihn auf einen geeigneten Wert, um die Anzahl der Entitäten zu steuern, die pro Iteration zurückgegeben werden. |
withParams |
Gibt die Parameter der Suche im JSON-Format an. Weitere Informationen finden Sie unter searchIterator(). |
Abfrage mit einem Iterator
Um mit einem Iterator abzufragen, rufen Sie die Methode query_iterator() auf:
Um mit einem Iterator zu suchen, rufen Sie die Methode queryIterator() auf:
# 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]
// ]
Parameter | Beschreibung |
---|---|
batch_size |
Die Anzahl der Entitäten, die jedes Mal zurückgegeben werden sollen, wenn Sie next() für den aktuellen Iterator aufrufen.Der Standardwert ist 1000. Setzen Sie ihn auf einen geeigneten Wert, um die Anzahl der Entitäten zu steuern, die pro Iteration zurückgegeben werden sollen. |
expr |
Eine skalare Filterbedingung, um übereinstimmende Entitäten zu filtern. Der Standardwert ist None, was anzeigt, dass die skalare Filterung ignoriert wird. Um eine skalare Filterbedingung zu erstellen, siehe Boolesche Ausdrucksregeln. |
output_fields |
Eine Liste von Feldnamen, die in jeder zurückgegebenen Entität enthalten sein sollen. Der Standardwert ist None. Wenn er nicht angegeben wird, wird nur das Primärfeld einbezogen. |
limit |
Die Gesamtzahl der zurückzugebenden Entitäten. Der Standardwert ist -1, was bedeutet, dass alle passenden Entitäten zurückgegeben werden. |
Parameter | Beschreibung |
---|---|
withCollectionName |
Legt den Namen der Sammlung fest. Der Sammlungsname darf nicht leer oder null sein. |
withExpr |
Legen Sie den Ausdruck für die Abfrage von Entitäten fest. Um eine skalare Filterbedingung zu erstellen, siehe Boolesche Ausdrucksregeln. |
withBatchSize |
Die Anzahl der Entitäten, die bei jedem Aufruf von next() für den aktuellen Iterator zurückgegeben werden sollen.Der Standardwert ist 1000. Setzen Sie ihn auf einen geeigneten Wert, um die Anzahl der pro Iteration zurückzugebenden Entitäten zu steuern. |
addOutField |
Gibt ein skalares Ausgabefeld an (Optional). |