Inserimento o aggiornamento di entità
L'operazione " upsert " offre un modo pratico per inserire o aggiornare entità in una raccolta.
Panoramica
È possibile utilizzare " upsert " per inserire una nuova entità o aggiornare una esistente, a seconda che la chiave primaria fornita nella richiesta "upsert" esista o meno nella collezione. Se la chiave primaria non viene trovata, viene eseguita un'operazione di inserimento. In caso contrario, verrà eseguita un'operazione di aggiornamento.
Un upsert in Milvus funziona sia in modalità di sovrascrittura che in modalità di unione.
Upsert in modalità "override"
Una richiesta di " upsert " in modalità "override" combina un'operazione di inserimento e una di eliminazione. Quando viene ricevuta una richiesta di " " per un'entità esistente, Milvus inserisce i dati contenuti nel payload della richiesta ed elimina contemporaneamente l'entità esistente con la chiave primaria originale specificata nei dati.
Upsert in modalità "override "
Se la collezione di destinazione ha l’ autoID abilitato sul proprio campo primario, la richiesta upsert deve comunque includere la chiave primaria dell’entità di destinazione. Milvus utilizza la chiave primaria fornita per individuare l’entità da sostituire e genera una nuova chiave primaria per i dati contenuti nel payload della richiesta prima di inserirli.
Per i campi con l’ nullable abilitato, è possibile ometterli nella richiesta upsert se non richiedono alcun aggiornamento.
Upsert in modalità mergeCompatible with Milvus v2.6.2+
È inoltre possibile utilizzare il flag ` partial_update ` per far funzionare una richiesta di upsert in modalità merge. Ciò consente di includere nel payload della richiesta solo i campi che necessitano di aggiornamento.
Upsert in modalità merge
Per eseguire un merge, impostare ` partial_update ` su ` True ` nella richiesta ` upsert ` insieme alla chiave primaria e ai campi da aggiornare con i loro nuovi valori.
Alla ricezione di tale richiesta, Milvus esegue una query con forte coerenza per recuperare l’entità, aggiorna i valori dei campi in base ai dati presenti nella richiesta, inserisce i dati modificati e infine elimina l’entità esistente con la chiave primaria originale contenuta nella richiesta.
Per i campi di tipo " ARRAY ", la modalità di unione supporta due operatori in Milvus v2.6.17 e versioni successive: " ARRAY_APPEND " e " ARRAY_REMOVE". Questi operatori consentono di aggiungere elementi o rimuovere elementi corrispondenti da un campo " ARRAY " esistente, senza dover prima eseguire una query sull'entità per recuperarne il valore corrente. Per ulteriori dettagli, consultare la sezione "Upsert dei campi ARRAY in modalità di unione".
Comportamenti di Upsert: note speciali
Ci sono diverse note speciali da tenere in considerazione prima di utilizzare la funzionalità di unione. I casi seguenti presuppongono che si disponga di una collezione con due campi scalari denominati title e issue, insieme a una chiave primaria id e a un campo vettoriale denominato vector.
Upsert dei campi con l’opzione «
nullable» abilitata.Supponiamo che il campo
issuepossa essere nullo. Quando si esegue l’upsert di questi campi, tenere presente che:Se si omette il campo `
issue` nella richiesta `upsert` e si disabilita `partial_update`, il campo `issue` verrà aggiornato a `null` invece di mantenere il suo valore originale.Per mantenere il valore originale del campo
issue, è necessario abilitarepartial_updatee omettere il campoissueoppure includere il campoissuecon il suo valore originale nella richiestaupsert.
Chiavi di upsert nel campo dinamico.
Supponiamo di aver abilitato la chiave dinamica nella raccolta di esempio e che le coppie chiave-valore nel campo dinamico di un'entità siano simili a
{"author": "John", "year": 2020, "tags": ["fiction"]}.Quando si esegue l’upsert dell’entità con chiavi quali
author,yearotags, oppure si aggiungono altre chiavi, tenere presente che:Se si esegue un'operazione di upsert con l'opzione "
partial_update" disabilitata, il comportamento predefinito è la sovrascrittura. Ciò significa che il valore del campo dinamico verrà sovrascritto da tutti i campi non definiti dallo schema inclusi nella richiesta e dai relativi valori.Ad esempio, se i dati inclusi nella richiesta sono
{"author": "Jane", "genre": "fantasy"}, le coppie chiave-valore nel campo dinamico dell’entità di destinazione verranno aggiornate in base a tali valori.Se si esegue un upsert con l'opzione `
partial_update` abilitata, il comportamento predefinito è la fusione. Ciò significa che il valore del campo dinamico si fonderà con tutti i campi non definiti dallo schema inclusi nella richiesta e con i relativi valori.Ad esempio, se i dati inclusi nella richiesta sono
{"author": "John", "year": 2020, "tags": ["fiction"]}, le coppie chiave-valore nel campo dinamico dell’entità di destinazione diventeranno{"author": "John", "year": 2020, "tags": ["fiction"], "genre": "fantasy"}dopo l’`upsert`.
Upsert di un campo JSON.
Supponiamo che la collezione di esempio abbia un campo JSON definito dallo schema denominato
extrase che le coppie chiave-valore in questo campo JSON di un'entità siano simili a{"author": "John", "year": 2020, "tags": ["fiction"]}.Quando si esegue l’upsert del campo
extrasdi un’entità con dati JSON modificati, si noti che il campo JSON viene trattato nel suo insieme e non è possibile aggiornare singole chiavi in modo selettivo. In altre parole, il campo JSON NON supporta l’upsert in modalità di unione.E seguire l’upsert di un campo `
ARRAY`.Per impostazione predefinita, un campo
ARRAYin modalità merge segue la semantica REPLACE: il valore contenuto nella richiesta sovrascrive l'array esistente. Per aggiornamenti più granulari, Milvus v2.6.17 e versioni successive supportano anche due operatori:ARRAY_APPENDaggiunge gli elementi presenti nel payload della richiesta all’array esistente.ARRAY_REMOVErimuove dall’array esistente ogni elemento che corrisponda a un valore presente nel payload della richiesta.
Per la sintassi degli operatori, i tipi di elementi supportati e altri vincoli, consultare Upsert dei campi ARRAY in modalità merge.
Upsert di un campo StructArray.
L'upsert di un campo StructArray in un'entità sovrascrive il valore del campo. A tal fine, è necessario fornire un elenco di dizionari, ciascuno dei quali contiene tutti i sottocampi definiti nello schema della struttura, anche quando si esegue l'upsert in modalità merge.
Per ulteriori dettagli, consultare Upsert di un campo StructArray in modalità merge.
Limiti e restrizioni
In base a quanto sopra, è necessario rispettare diversi limiti e restrizioni:
La richiesta "
upsert" deve sempre includere le chiavi primarie delle entità di destinazione, anche quando è abilitata l'opzione "autoID". Per le collezioni "autoID", le chiavi primarie nella richiesta identificano le entità esistenti da sostituire. Milvus genera nuove chiavi primarie per le entità di sostituzione inserite.La collezione di destinazione deve essere caricata e disponibile per le query.
Tutti i campi specificati nella richiesta devono esistere nello schema della collezione di destinazione.
I valori di tutti i campi specificati nella richiesta devono corrispondere ai tipi di dati definiti nello schema.
Per qualsiasi campo derivato da un altro tramite funzioni, Milvus rimuoverà il campo derivato durante l’upsert per consentire il ricalcolo.
Upsert di entità in una collezione
In questa sezione, eseguiremo l'upsert di entità in una collezione denominata my_collection. Questa collezione presenta solo due campi, denominati id, vector, title e issue. Il campo id è il campo primario, mentre i campi title e issue sono campi scalari.
Le tre entità, se presenti nella collezione, verranno sovrascritte da quelle incluse nella richiesta di upsert.
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" \
--header "Request-Timeout: 10" \
-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 di entità in una partizione
È inoltre possibile eseguire l'upsert di entità in una partizione specificata. I seguenti frammenti di codice presuppongono che nella collezione sia presente una partizione denominata PartitionA.
Le tre entità, se presenti nella partizione, verranno sovrascritte da quelle incluse nella richiesta.
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" \
--header "Request-Timeout: 10" \
-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 di entità in modalità mergeCompatible with Milvus v2.6.2+
L'esempio di codice seguente illustra come eseguire l'upsert di entità con aggiornamenti parziali. È sufficiente specificare solo i campi che richiedono aggiornamenti e i relativi nuovi valori, insieme al flag esplicito di aggiornamento parziale.
Nell’esempio seguente, il campo ` issue ` delle entità specificate nella richiesta di upsert verrà aggiornato con i valori inclusi nella richiesta.
Quando si esegue un upsert in modalità merge, assicurarsi che le entità coinvolte nella richiesta abbiano lo stesso insieme di campi. Supponendo che vi siano due o più entità da sottoporre a upsert, come mostrato nel seguente frammento di codice, è importante che includano campi identici per evitare errori e mantenere l’integrità dei dati.
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 "Request-Timeout: 10" \
-H "Authorization: Bearer ${TOKEN}" \
-d "{
\"collectionName\": \"${COLLECTION_NAME}\",
\"data\": ${UPSERT_DATA},
\"partialUpdate\": true
}"
# {
# "code": 0,
# "data": {
# "upsertCount": 2,
# "upsertIds": [
# 3,
# 12,
# ]
# }
# }
Upsert dei campi ARRAY in modalità mergeCompatible with Milvus 2.6.17+
Prima di Milvus v2.6.17, l’aggiornamento di una parte di un campo di tipo « ARRAY » richiedeva un flusso di lettura-modifica-scrittura lato client: interrogare l’array esistente, modificarlo nel codice dell’applicazione ed eseguire l’upsert del valore di sostituzione completo. Gli operatori di aggiornamento parziale (ARRAY_APPEND e ARRAY_REMOVE) consentono di inviare solo gli elementi da aggiungere o rimuovere, riducendo così la logica lato client ed evitando la lettura aggiuntiva prima dell’upsert.
Supponiamo che l’entità con chiave primaria 1 contenga già tags = ["new", "trial"]. Prima dell’introduzione degli operatori di aggiornamento parziale, l’aggiunta dell’elemento "premium" a un array richiedeva l’upsert dell’intero array sostitutivo:
client.upsert(
collection_name="users",
data=[{"pk": 1, "tags": ["new", "trial", "premium"]}],
partial_update=True,
)
List<JsonObject> replacementData = Collections.singletonList(
gson.fromJson("{\"pk\": 1, \"tags\": [\"new\", \"trial\", \"premium\"]}", JsonObject.class)
);
client.upsert(UpsertReq.builder()
.collectionName("users")
.partialUpdate(true)
.data(replacementData)
.build());
// nodejs
// go
# restful
Con ARRAY_APPEND, invia solo l’elemento da aggiungere:
client.upsert(
collection_name="users",
data=[{"pk": 1, "tags": ["premium"]}],
field_ops={"tags": FieldOp.array_append()},
)
List<JsonObject> appendData = Collections.singletonList(
gson.fromJson("{\"pk\": 1, \"tags\": [\"premium\"]}", JsonObject.class)
);
UpsertReq.FieldPartialUpdateOp appendTags = UpsertReq.FieldPartialUpdateOp.builder()
.fieldName("tags")
.opType(UpsertReq.FieldPartialUpdateOp.OpType.ARRAY_APPEND)
.build();
client.upsert(UpsertReq.builder()
.collectionName("users")
.data(appendData)
.fieldOps(Collections.singletonList(appendTags))
.build());
// nodejs
// go
# restful
Con ` ARRAY_REMOVE`, invia solo l'elemento corrispondente da rimuovere:
client.upsert(
collection_name="users",
data=[{"pk": 1, "tags": ["trial"]}],
field_ops={"tags": FieldOp.array_remove()},
)
List<JsonObject> removeData = Collections.singletonList(
gson.fromJson("{\"pk\": 1, \"tags\": [\"trial\"]}", JsonObject.class)
);
UpsertReq.FieldPartialUpdateOp removeTags = UpsertReq.FieldPartialUpdateOp.builder()
.fieldName("tags")
.opType(UpsertReq.FieldPartialUpdateOp.OpType.ARRAY_REMOVE)
.build();
client.upsert(UpsertReq.builder()
.collectionName("users")
.data(removeData)
.fieldOps(Collections.singletonList(removeTags))
.build());
// nodejs
// go
# restful
L'associazione di uno dei due operatori a un campo tramite field_ops abilita implicitamente la semantica dell'aggiornamento parziale. Pertanto, non è necessario passare partial_update=True insieme a field_ops.
Limiti
I valori del payload devono corrispondere all'
element_typedel campo di destinazioneARRAY. Ad esempio, se il campo di destinazione èARRAY<VARCHAR>, il payload deve contenere valori di tipo stringa.A partire da Milvus v2.6.17, i campi
ARRAY_APPENDeARRAY_REMOVEsupportano i campiARRAYil cuielement_typeèBOOL,INT8,INT16,INT32,INT64,FLOAT,DOUBLEoVARCHAR.Dopo un'operazione di
ARRAY_APPEND, la lunghezza dell'array risultante non deve superare il valore specificato nel campomax_capacity.Gli upsert concorrenti sulla stessa entità non sono atomici tra le richieste. Se due richieste aggiornano contemporaneamente lo stesso campo
ARRAY, la scrittura successiva può sovrascrivere quella precedente. Utilizzare il coordinamento a livello di applicazione se è necessario preservare tutte le modifiche concorrenti.
Esempio
L’esempio seguente utilizza una piccola collezione users con una chiave primaria pk, un campo tags di tipo ARRAY<VARCHAR> e un campo vettore embedding. Innanzitutto inserisce due entità con valori iniziali tags, quindi utilizza ARRAY_APPEND e ARRAY_REMOVE per mostrare come ciascun operatore modifichi l’array memorizzato.
from pymilvus import DataType, FieldOp, MilvusClient
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus"
)
# 1. Create a collection with an ARRAY<VARCHAR> field
schema = client.create_schema(enable_dynamic_field=False)
schema.add_field("pk", DataType.INT64, is_primary=True)
schema.add_field("embedding", DataType.FLOAT_VECTOR, dim=5)
schema.add_field(
"tags",
DataType.ARRAY,
element_type=DataType.VARCHAR,
max_capacity=8,
max_length=32,
)
index_params = client.prepare_index_params()
index_params.add_index(
field_name="embedding",
index_type="AUTOINDEX",
metric_type="L2",
)
client.create_collection(
collection_name="users",
schema=schema,
index_params=index_params
)
# 2. Seed two entities
client.insert(
collection_name="users",
data=[
{"pk": 1, "embedding": [0.1, 0.2, 0.3, 0.4, 0.5], "tags": ["new"]},
{"pk": 2, "embedding": [0.6, 0.7, 0.8, 0.9, 1.0], "tags": ["new", "trial"]},
],
)
# 3. Append tags without reading the existing ARRAY values
client.upsert(
collection_name="users",
data=[
{"pk": 1, "tags": ["premium", "vip"]},
{"pk": 2, "tags": ["premium"]},
],
field_ops={"tags": FieldOp.array_append()},
)
res = client.query(
collection_name="users",
filter="pk in [1, 2]",
output_fields=["pk", "tags"],
)
print(res)
# Example output:
# data: [
# "{'pk': 1, 'tags': ['new', 'premium', 'vip']}",
# "{'pk': 2, 'tags': ['new', 'trial', 'premium']}"
# ]
# 4. Remove matching tags without replacing the full ARRAY field
client.upsert(
collection_name="users",
data=[
{"pk": 1, "tags": ["new"]},
{"pk": 2, "tags": ["trial"]},
],
field_ops={"tags": FieldOp.array_remove()},
)
res = client.query(
collection_name="users",
filter="pk in [1, 2]",
output_fields=["pk", "tags"],
)
print(res)
# Example output:
# data: [
# "{'pk': 1, 'tags': ['premium', 'vip']}",
# "{'pk': 2, 'tags': ['new', 'premium']}"
# ]
// java
// nodejs
// go
# restful
Upsert del campo StructArray in modalità merge
L’upsert di un campo StructArray in un’entità sovrascrive il valore del campo. Ciò significa che è necessario includere tutti i sottocampi definiti nello schema della struttura quando si esegue l’upsert di un campo StructArray.
L'esempio seguente illustra come eseguire l'upsert del campo ` chunks ` in modalità merge, un campo StructArray con 6 sottocampi. Al termine dell'operazione, il campo ` chunks ` dell'entità con id 1 viene impostato sull'array contenente le strutture a due elementi fornite nella richiesta.
client.upsert(
collection_name="books",
data=[{
"id": 1,
"chunks": [
{
"text": "Use HNSW efSearch to trade recall for latency.",
"section": "index",
"page": 1,
"quality_score": 0.92,
"has_code": True,
"emb_list_vector": [0.11, 0.21, 0.31, 0.41]
},
{
"text": "Range search returns vectors within a distance boundary.",
"section": "search",
"page": 2,
"quality_score": 0.86,
"has_code": False,
"emb_list_vector": [0.18, 0.23, 0.29, 0.36]
}
]
}],
partial_update=True
)
// java
// nodejs
// go
# restful