Upsert Entitäten
Die Operation upsert bietet eine bequeme Möglichkeit zum Einfügen oder Aktualisieren von Entitäten in einer Sammlung.
Überblick
Sie können upsert verwenden, um entweder eine neue Entität einzufügen oder eine vorhandene zu aktualisieren, je nachdem, ob der in der Upsert-Anforderung angegebene Primärschlüssel in der Sammlung vorhanden ist. Wenn der Primärschlüssel nicht gefunden wird, wird ein Einfügevorgang durchgeführt. Andernfalls wird ein Aktualisierungsvorgang durchgeführt.
Ein Upsert in Milvus funktioniert entweder im Override- oder im Merge-Modus.
Upsert im Überschreibungsmodus
Eine Upsert-Anfrage, die im Override-Modus arbeitet, kombiniert einen Einfüge- und einen Löschvorgang. Wenn eine upsert -Anfrage für eine bestehende Entität empfangen wird, fügt Milvus die in der Nutzlast der Anfrage enthaltenen Daten ein und löscht gleichzeitig die bestehende Entität mit dem ursprünglichen Primärschlüssel, der in den Daten angegeben ist.
Upsert im Überschreibungsmodus
Wenn die Zielsammlung die Option autoid für ihr Primärfeld aktiviert hat, generiert Milvus einen neuen Primärschlüssel für die in der Nutzlast der Anforderung enthaltenen Daten, bevor es sie einfügt.
Bei Feldern, für die nullable aktiviert ist, können Sie sie in der Anforderung upsert auslassen, wenn sie keine Aktualisierungen erfordern.
Upsert im ZusammenführungsmodusCompatible with Milvus v2.6.2+
Sie können auch das Kennzeichen partial_update verwenden, um eine Upsert-Anfrage im Merge-Modus zu bearbeiten. Dadurch können Sie nur die Felder, die aktualisiert werden müssen, in die Nutzlast der Anforderung aufnehmen.
Upsert im Zusammenführungsmodus
Um eine Zusammenführung durchzuführen, setzen Sie partial_update auf True in der Anforderung upsert zusammen mit dem Primärschlüssel und den Feldern, die mit ihren neuen Werten aktualisiert werden sollen.
Beim Empfang einer solchen Anforderung führt Milvus eine Abfrage mit starker Konsistenz durch, um die Entität abzurufen, aktualisiert die Feldwerte auf der Grundlage der Daten in der Anforderung, fügt die geänderten Daten ein und löscht dann die vorhandene Entität mit dem ursprünglichen Primärschlüssel in der Anforderung.
Upsert-Verhalten: besondere Hinweise
Es gibt einige besondere Hinweise, die Sie beachten sollten, bevor Sie die Zusammenführungsfunktion verwenden. In den folgenden Fällen wird davon ausgegangen, dass Sie eine Sammlung mit zwei skalaren Feldern namens title und issue sowie einem Primärschlüssel id und einem Vektorfeld namens vector haben.
Upsert-Felder mit
nullableaktiviert.Nehmen Sie an, dass das Feld
issueNull sein kann. Wenn Sie diese Felder einfügen, beachten Sie das:Wenn Sie das Feld
issuein der Anforderungupsertauslassen undpartial_updatedeaktivieren, wird das Feldissueaufnullaktualisiert, anstatt seinen ursprünglichen Wert beizubehalten.Um den ursprünglichen Wert des Feldes
issuebeizubehalten, müssen Sie entwederpartial_updateaktivieren und das Feldissueauslassen oder das Feldissuemit seinem ursprünglichen Wert in die Anforderungupsertaufnehmen.
Upsert-Schlüssel im dynamischen Feld.
Angenommen, Sie haben den dynamischen Schlüssel in der Beispielsammlung aktiviert, und die Schlüssel-Wert-Paare im dynamischen Feld einer Entität sind ähnlich wie
{"author": "John", "year": 2020, "tags": ["fiction"]}.Wenn Sie die Entität mit Schlüsseln wie
author,yearodertagseinfügen oder andere Schlüssel hinzufügen, beachten Sie Folgendes:Wenn Sie mit deaktiviertem
partial_updateeinfügen, ist das Standardverhalten, dass das dynamische Feld überschrieben wird. Das bedeutet, dass der Wert des dynamischen Feldes von allen nicht schema-definierten Feldern, die in der Anfrage enthalten sind, und deren Werten überschrieben wird.Wenn die in der Anfrage enthaltenen Daten beispielsweise
{"author": "Jane", "genre": "fantasy"}sind, werden die Schlüssel-Wert-Paare im dynamischen Feld der Zielentität auf diesen Wert aktualisiert.Wenn Sie upsert mit
partial_updateaktivieren, ist das Standardverhalten das Zusammenführen. Das bedeutet, dass der Wert des dynamischen Feldes mit allen nicht schema-definierten Feldern, die in der Anfrage enthalten sind, und deren Werten zusammengeführt wird.Wenn die in der Anfrage enthaltenen Daten beispielsweise
{"author": "John", "year": 2020, "tags": ["fiction"]}sind, werden die Schlüssel-Wert-Paare im dynamischen Feld der Zielentität nach dem Upsert zu{"author": "John", "year": 2020, "tags": ["fiction"], "genre": "fantasy"}.
Upsert eines JSON-Feldes.
Angenommen, die Beispielsammlung hat ein schema-definiertes JSON-Feld mit dem Namen
extrasund die Schlüssel-Wert-Paare in diesem JSON-Feld einer Entität sind ähnlich wie{"author": "John", "year": 2020, "tags": ["fiction"]}.Wenn Sie das Feld
extraseiner Entität mit geänderten JSON-Daten einfügen, beachten Sie, dass das JSON-Feld als Ganzes behandelt wird und Sie nicht einzelne Schlüssel selektiv aktualisieren können. Mit anderen Worten, das JSON-Feld unterstützt NICHT das Upserting im Merge-Modus.
Grenzen und Beschränkungen
Ausgehend von den oben genannten Inhalten sind einige Einschränkungen zu beachten:
Die Anfrage
upsertmuss immer die Primärschlüssel der Zielentitäten enthalten.Die Zielsammlung muss geladen und für Abfragen verfügbar sein.
Alle in der Anfrage angegebenen Felder müssen im Schema der Zielsammlung vorhanden sein.
Die Werte aller in der Abfrage angegebenen Felder müssen mit den im Schema definierten Datentypen übereinstimmen.
Für jedes Feld, das mit Hilfe von Funktionen von einem anderen abgeleitet wurde, entfernt Milvus das abgeleitete Feld während des Upsets, um eine Neuberechnung zu ermöglichen.
Upsert von Entitäten in einer Sammlung
In diesem Abschnitt werden wir Entitäten in eine Sammlung namens my_collection einfügen. Diese Sammlung hat nur zwei Felder, die id, vector, title und issue heißen. Das Feld id ist das Primärfeld, während die Felder title und issue Skalarfelder sind.
Die drei Entitäten werden, wenn sie in der Sammlung vorhanden sind, durch die in der Upsert-Anfrage enthaltenen überschrieben.
from pymilvus import MilvusClient
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus"
)
data=[
{
"id": 0,
"vector": [-0.619954382375778, 0.4479436794798608, -0.17493894838751745, -0.4248030059917294, -0.8648452746018911],
"title": "Artificial Intelligence in Real Life",
"issue": "vol.12"
}, {
"id": 1,
"vector": [0.4762662251462588, -0.6942502138717026, -0.4490002642657902, -0.628696575798281, 0.9660395877041965],
"title": "Hollow Man",
"issue": "vol.19"
}, {
"id": 2,
"vector": [-0.8864122635045097, 0.9260170474445351, 0.801326976181461, 0.6383943392381306, 0.7563037341572827],
"title": "Treasure Hunt in Missouri",
"issue": "vol.12"
}
]
res = client.upsert(
collection_name='my_collection',
data=data
)
print(res)
# Output
# {'upsert_count': 3}
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.vector.request.UpsertReq;
import io.milvus.v2.service.vector.response.UpsertResp;
import java.util.*;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.token("root:Milvus")
.build());
Gson gson = new Gson();
List<JsonObject> data = Arrays.asList(
gson.fromJson("{\"id\": 0, \"vector\": [-0.619954382375778, 0.4479436794798608, -0.17493894838751745, -0.4248030059917294, -0.8648452746018911], \"title\": \"Artificial Intelligence in Real Life\", \"issue\": \"\vol.12\"}", JsonObject.class),
gson.fromJson("{\"id\": 1, \"vector\": [0.4762662251462588, -0.6942502138717026, -0.4490002642657902, -0.628696575798281, 0.9660395877041965], \"title\": \"Hollow Man\", \"issue\": \"vol.19\"}", JsonObject.class),
gson.fromJson("{\"id\": 2, \"vector\": [-0.8864122635045097, 0.9260170474445351, 0.801326976181461, 0.6383943392381306, 0.7563037341572827], \"title\": \"Treasure Hunt in Missouri\", \"issue\": \"vol.12\"}", JsonObject.class),
);
UpsertReq upsertReq = UpsertReq.builder()
.collectionName("my_collection")
.data(data)
.build();
UpsertResp upsertResp = client.upsert(upsertReq);
System.out.println(upsertResp);
// Output:
//
// UpsertResp(upsertCnt=3)
const { MilvusClient, DataType } = require("@zilliz/milvus2-sdk-node")
const address = "http://localhost:19530";
const token = "root:Milvus";
const client = new MilvusClient({address, token});
data = [
{id: 0, vector: [-0.619954382375778, 0.4479436794798608, -0.17493894838751745, -0.4248030059917294, -0.8648452746018911], title: "Artificial Intelligence in Real Life", issue: "vol.12"},
{id: 1, vector: [0.4762662251462588, -0.6942502138717026, -0.4490002642657902, -0.628696575798281, 0.9660395877041965], title: "Hollow Man", issue: "vol.19"},
{id: 2, vector: [-0.8864122635045097, 0.9260170474445351, 0.801326976181461, 0.6383943392381306, 0.7563037341572827], title: "Treasure Hunt in Missouri", issue: "vol.12"},
]
res = await client.upsert({
collection_name: "my_collection",
data: data,
})
console.log(res.upsert_cnt)
// Output
//
// 3
//
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v2/column"
"github.com/milvus-io/milvus/client/v2/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
milvusAddr := "localhost:19530"
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: milvusAddr,
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
titleColumn := column.NewColumnString("title", []string{
"Artificial Intelligence in Real Life", "Hollow Man", "Treasure Hunt in Missouri",
})
issueColumn := column.NewColumnString("issue", []string{
"vol.12", "vol.19", "vol.12"
})
_, err = client.Upsert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection").
WithInt64Column("id", []int64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}).
WithFloatVectorColumn("vector", 5, [][]float32{
{0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592},
{0.19886812562848388, 0.06023560599112088, 0.6976963061752597, 0.2614474506242501, 0.838729485096104},
{0.43742130801983836, -0.5597502546264526, 0.6457887650909682, 0.7894058910881185, 0.20785793220625592},
}).
WithColumns(titleColumn, issueColumn),
)
if err != nil {
fmt.Println(err.Error())
// handle err
}
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/upsert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"data": [
{"id": 0, "vector": [0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592], "title": "Artificial Intelligence in Real Life", "issue": "vol.12"},
{"id": 1, "vector": [0.19886812562848388, 0.06023560599112088, 0.6976963061752597, 0.2614474506242501, 0.838729485096104], "title": "Hollow Man", "issue": "vol.19"},
{"id": 2, "vector": [0.43742130801983836, -0.5597502546264526, 0.6457887650909682, 0.7894058910881185, 0.20785793220625592], "title": "Treasure Hunt in Missouri", "issue": "vol.12"},
],
"collectionName": "my_collection"
}'
# {
# "code": 0,
# "data": {
# "upsertCount": 3,
# "upsertIds": [
# 0,
# 1,
# 2,
# ]
# }
# }
Upsert Entitäten in einer Partition
Sie können Entitäten auch in eine bestimmte Partition einfügen. Die folgenden Codeschnipsel gehen davon aus, dass Sie eine Partition namens PartitionA in Ihrer Sammlung haben.
Die drei Entitäten, falls in der Partition vorhanden, werden durch die in der Anfrage enthaltenen überschrieben.
data=[
{
"id": 10,
"vector": [0.06998888224297328, 0.8582816610326578, -0.9657938677934292, 0.6527905683627726, -0.8668460657158576],
"title": "Layour Design Reference",
"issue": "vol.34"
},
{
"id": 11,
"vector": [0.6060703043917468, -0.3765080534566074, -0.7710758854987239, 0.36993888322346136, 0.5507513364206531],
"title": "Doraemon and His Friends",
"issue": "vol.2"
},
{
"id": 12,
"vector": [-0.9041813104515337, -0.9610546012461163, 0.20033003106083358, 0.11842506351635174, 0.8327356724591011],
"title": "Pikkachu and Pokemon",
"issue": "vol.12"
},
]
res = client.upsert(
collection_name="my_collection",
data=data,
partition_name="partitionA"
)
print(res)
# Output
# {'upsert_count': 3}
import io.milvus.v2.service.vector.request.UpsertReq;
import io.milvus.v2.service.vector.response.UpsertResp;
Gson gson = new Gson();
List<JsonObject> data = Arrays.asList(
gson.fromJson("{\"id\": 10, \"vector\": [0.06998888224297328, 0.8582816610326578, -0.9657938677934292, 0.6527905683627726, -0.8668460657158576], \"title\": \"Layour Design Reference\", \"issue\": \"vol.34\"}", JsonObject.class),
gson.fromJson("{\"id\": 11, \"vector\": [0.6060703043917468, -0.3765080534566074, -0.7710758854987239, 0.36993888322346136, 0.5507513364206531], \"title\": \"Doraemon and His Friends\", \"issue\": \"vol.2\"}", JsonObject.class),
gson.fromJson("{\"id\": 12, \"vector\": [-0.9041813104515337, -0.9610546012461163, 0.20033003106083358, 0.11842506351635174, 0.8327356724591011], \"title\": \"Pikkachu and Pokemon\", \"issue\": \"vol.12\"}", JsonObject.class),
);
UpsertReq upsertReq = UpsertReq.builder()
.collectionName("my_collection")
.partitionName("partitionA")
.data(data)
.build();
UpsertResp upsertResp = client.upsert(upsertReq);
System.out.println(upsertResp);
// Output:
//
// UpsertResp(upsertCnt=3)
const { MilvusClient, DataType } = require("@zilliz/milvus2-sdk-node")
// 6. Upsert data in partitions
data = [
{id: 10, vector: [0.06998888224297328, 0.8582816610326578, -0.9657938677934292, 0.6527905683627726, -0.8668460657158576], title: "Layour Design Reference", issue: "vol.34"},
{id: 11, vector: [0.6060703043917468, -0.3765080534566074, -0.7710758854987239, 0.36993888322346136, 0.5507513364206531], title: "Doraemon and His Friends", issue: "vol.2"},
{id: 12, vector: [-0.9041813104515337, -0.9610546012461163, 0.20033003106083358, 0.11842506351635174, 0.8327356724591011], title: "Pikkachu and Pokemon", issue: "vol.12"},
]
res = await client.upsert({
collection_name: "my_collection",
data: data,
partition_name: "partitionA"
})
console.log(res.upsert_cnt)
// Output
//
// 3
//
titleColumn = column.NewColumnString("title", []string{
"Layour Design Reference", "Doraemon and His Friends", "Pikkachu and Pokemon",
})
issueColumn = column.NewColumnString("issue", []string{
"vol.34", "vol.2", "vol.12",
})
_, err = client.Upsert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection").
WithPartition("partitionA").
WithInt64Column("id", []int64{10, 11, 12, 13, 14, 15, 16, 17, 18, 19}).
WithFloatVectorColumn("vector", 5, [][]float32{
{0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592},
{0.19886812562848388, 0.06023560599112088, 0.6976963061752597, 0.2614474506242501, 0.838729485096104},
{0.43742130801983836, -0.5597502546264526, 0.6457887650909682, 0.7894058910881185, 0.20785793220625592},
}).
WithColumns(titleColumn, issueColumn),
)
if err != nil {
fmt.Println(err.Error())
// handle err
}
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/upsert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"data": [
{"id": 10, "vector": [0.06998888224297328, 0.8582816610326578, -0.9657938677934292, 0.6527905683627726, -0.8668460657158576], "title": "Layour Design Reference", "issue": "vol.34"},
{"id": 11, "vector": [0.6060703043917468, -0.3765080534566074, -0.7710758854987239, 0.36993888322346136, 0.5507513364206531], "title": "Doraemon and His Friends", "issue": "vol.2"},
{"id": 12, "vector": [-0.9041813104515337, -0.9610546012461163, 0.20033003106083358, 0.11842506351635174, 0.8327356724591011], "title": "Pikkachu and Pokemon", "issue": "vol.12"},
],
"collectionName": "my_collection",
"partitionName": "partitionA"
}'
# {
# "code": 0,
# "data": {
# "upsertCount": 3,
# "upsertIds": [
# 10,
# 11,
# 12,
# ]
# }
# }
Upsert Entitäten im Merge-ModusCompatible with Milvus v2.6.2+
Das folgende Codebeispiel zeigt, wie man Entitäten mit teilweisen Aktualisierungen einfügt. Geben Sie nur die zu aktualisierenden Felder und ihre neuen Werte an, zusammen mit dem expliziten Flag für partielle Aktualisierung.
Im folgenden Beispiel wird das Feld issue der Entitäten, die in der Upsert-Anforderung angegeben sind, auf die in der Anforderung enthaltenen Werte aktualisiert.
Wenn Sie ein Upsert im Merge-Modus durchführen, stellen Sie sicher, dass die an der Anforderung beteiligten Entitäten den gleichen Satz von Feldern haben. Angenommen, es gibt zwei oder mehr Entitäten, die upserted werden sollen, wie im folgenden Codeschnipsel gezeigt, ist es wichtig, dass sie identische Felder enthalten, um Fehler zu vermeiden und die Datenintegrität zu wahren.
data=[
{
"id": 1,
"issue": "vol.14"
},
{
"id": 2,
"issue": "vol.7"
}
]
res = client.upsert(
collection_name="my_collection",
data=data,
partial_update=True
)
print(res)
# Output
# {'upsert_count': 2}
JsonObject row1 = new JsonObject();
row1.addProperty("id", 1);
row1.addProperty("issue", "vol.14");
JsonObject row2 = new JsonObject();
row2.addProperty("id", 2);
row2.addProperty("issue", "vol.7");
UpsertReq upsertReq = UpsertReq.builder()
.collectionName("my_collection")
.data(Arrays.asList(row1, row2))
.partialUpdate(true)
.build();
UpsertResp upsertResp = client.upsert(upsertReq);
System.out.println(upsertResp);
// Output:
//
// UpsertResp(upsertCnt=2)
pkColumn := column.NewColumnInt64("id", []int64{1, 2})
issueColumn = column.NewColumnString("issue", []string{
"vol.17", "vol.7",
})
_, err = client.Upsert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection").
WithColumns(pkColumn, issueColumn).
WithPartialUpdate(true),
)
if err != nil {
fmt.Println(err.Error())
// handle err
}
const data=[
{
"id": 1,
"issue": "vol.14"
},
{
"id": 2,
"issue": "vol.7"
}
];
const res = await client.upsert({
collection_name: "my_collection",
data,
partial_update: true
});
console.log(res)
// Output
//
// 2
//
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
export COLLECTION_NAME="my_collection"
export UPSERT_DATA='[
{
"id": 1,
"issue": "vol.14"
},
{
"id": 2,
"issue": "vol.7"
}
]'
curl -X POST "http://localhost:19530/v2/vectordb/entities/upsert" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${TOKEN}" \
-d "{
\"collectionName\": \"${COLLECTION_NAME}\",
\"data\": ${UPSERT_DATA},
\"partialUpdate\": true
}"
# {
# "code": 0,
# "data": {
# "upsertCount": 2,
# "upsertIds": [
# 3,
# 12,
# ]
# }
# }