Insertar entidades
La operación upsert proporciona una forma cómoda de insertar o actualizar entidades en una colección.
Visión general
Puede utilizar upsert para insertar una nueva entidad o actualizar una existente, dependiendo de si la clave primaria proporcionada en la solicitud upsert existe en la colección. Si no se encuentra la clave primaria, se realizará una operación de inserción. En caso contrario, se realizará una operación de actualización.
Un upsert en Milvus funciona en modo override o merge.
Upsert en modo override
Una solicitud de upsert que funciona en modo override combina una inserción y una eliminación. Cuando se recibe una solicitud de upsert para una entidad existente, Milvus inserta los datos incluidos en la carga útil de la solicitud y elimina al mismo tiempo la entidad existente con la clave primaria original especificada en los datos.
Upsert en modo de anulación
Si la colección de destino tiene autoid habilitado en su campo primario, Milvus generará una nueva clave primaria para los datos transportados en la carga útil de la petición antes de insertarlos.
Para los campos con nullable habilitado, puede omitirlos en la solicitud upsert si no requieren ninguna actualización.
Upsert en modo fusiónCompatible with Milvus v2.6.2+
También puede utilizar el indicador partial_update para que una solicitud upsert funcione en modo fusión. Esto le permite incluir sólo los campos que necesitan actualización en la carga útil de la solicitud.
Upsert en modo merge
Para realizar una fusión, establezca partial_update en True en la solicitud upsert junto con la clave primaria y los campos que desea actualizar con sus nuevos valores.
Al recibir una solicitud de este tipo, Milvus realiza una consulta con coherencia fuerte para recuperar la entidad, actualiza los valores de los campos basándose en los datos de la solicitud, inserta los datos modificados y, a continuación, elimina la entidad existente con la clave primaria original que figura en la solicitud.
Comportamientos Upsert: notas especiales
Hay varias notas especiales que debe tener en cuenta antes de utilizar la función de fusión. Los siguientes casos suponen que tiene una colección con dos campos escalares denominados title y issue, junto con una clave primaria id y un campo vectorial denominado vector.
Campos Upsert con
nullableactivado.Supongamos que el campo
issuepuede ser nulo. Al upsert estos campos, tenga en cuenta que:Si omite el campo
issueen la solicitudupserty desactivapartial_update, el campoissuese actualizará anullen lugar de conservar su valor original.Para conservar el valor original del campo
issue, debe activarpartial_updatey omitir el campoissueo incluir el campoissuecon su valor original en la solicitudupsert.
Insertar claves en el campo dinámico.
Supongamos que ha activado la clave dinámica en la colección de ejemplo y que los pares clave-valor del campo dinámico de una entidad son similares a
{"author": "John", "year": 2020, "tags": ["fiction"]}.Cuando reinserte la entidad con claves como
author,year, otags, o añada otras claves, tenga en cuenta lo siguiente:Si upsert con
partial_updatedesactivado, el comportamiento por defecto es anular. Esto significa que el valor del campo dinámico será anulado por todos los campos no definidos por el esquema incluidos en la solicitud y sus valores.Por ejemplo, si los datos incluidos en la solicitud son
{"author": "Jane", "genre": "fantasy"}, los pares clave-valor del campo dinámico de la entidad de destino se actualizarán a ese valor.Si upsert con
partial_updateactivado, el comportamiento por defecto es fusionar. Esto significa que el valor del campo dinámico se fusionará con todos los campos no definidos por el esquema incluidos en la solicitud y sus valores.Por ejemplo, si los datos incluidos en la solicitud son
{"author": "John", "year": 2020, "tags": ["fiction"]}, los pares clave-valor del campo dinámico de la entidad de destino se convertirán en{"author": "Jane", "year": 2020, "tags": ["fiction"], "genre": "fantasy"}tras la inserción ascendente.
Upsert de un campo JSON.
Supongamos que la colección de ejemplo tiene un campo JSON definido por esquema denominado
extras, y los pares clave-valor de este campo JSON de una entidad son similares a{"author": "John", "year": 2020, "tags": ["fiction"]}.Cuando haga upsert en el campo
extrasde una entidad con datos JSON modificados, tenga en cuenta que:Si upsert con
partial_updatedesactivado, el comportamiento por defecto es anular. Esto significa que el valor del campo JSON incluido en la solicitud anulará el valor original del campo JSON de la entidad de destino.Por ejemplo, si los datos incluidos en la solicitud son
{extras: {"author": "Jane", "genre": "fantasy"}}, los pares clave-valor del campoextrasde la entidad de destino se actualizarán a{"author": "Jane", "genre": "fantasy"}.Si upsert con
partial_updateactivado, el comportamiento por defecto es fusionar. Esto significa que el valor del campo JSON incluido en la solicitud se fusionará con el valor original del campo JSON de la entidad de destino.Por ejemplo, si los datos incluidos en la solicitud son
{extras: {"author": "Jane", "genre": "fantasy"}}, los pares clave-valor del campoextrasde la entidad de destino se convertirán en{"author": "Jane", "year": 2020, "tags": ["fiction"], "genre": "fantasy"}después de la udpate.
Límites y restricciones
Basándose en el contenido anterior, existen varios límites y restricciones a seguir:
La petición
upsertdebe incluir siempre las claves primarias de las entidades de destino.La colección de destino debe estar cargada y disponible para consultas.
Todos los campos especificados en la solicitud deben existir en el esquema de la colección de destino.
Los valores de todos los campos especificados en la petición deben coincidir con los tipos de datos definidos en el esquema.
Para cualquier campo derivado de otro mediante funciones, Milvus eliminará el campo derivado durante el upsert para permitir el recálculo.
Subir entidades de una colección
En esta sección, vamos a upsert entidades en una colección llamada my_collection. Esta colección sólo tiene dos campos, denominados id, vector, title, y issue. El campo id es el campo primario, mientras que los campos title y issue son campos escalares.
Las tres entidades, si existen en la colección, serán anuladas por las que incluya la petición 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" \
-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 entidades en una partición
También puedes upsert entidades en una partición especificada. Los siguientes fragmentos de código asumen que tienes una partición llamada ParticiónA en tu colección.
Las tres entidades, si existen en la partición, serán reemplazadas por las incluidas en la petición.
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 entidades en modo mergeCompatible with Milvus v2.6.2+
El siguiente ejemplo de código demuestra cómo upsert entidades con actualizaciones parciales. Proporcione sólo los campos que necesitan actualizaciones y sus nuevos valores, junto con la bandera de actualización parcial explícita.
En el siguiente ejemplo, el campo issue de las entidades especificadas en la solicitud de upsert se actualizará con los valores incluidos en la solicitud.
Al realizar una upsert en modo merge, asegúrese de que las entidades implicadas en la petición tienen el mismo conjunto de campos. Supongamos que hay dos o más entidades que se van a upsertar, como se muestra en el siguiente fragmento de código, es importante que incluyan campos idénticos para evitar errores y mantener la integridad de los datos.
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,
# ]
# }
# }