• نبذة عن ميلفوس
  • ابدأ الآن
  • المفاهيم
  • دليل المستخدم
  • استيراد البيانات
  • أدوات الذكاء الاصطناعي
  • دليل الإدارة
  • الأدوات
  • عمليات الدمج
  • البرامج التعليمية
  • الأسئلة الشائعة
  • API Reference

إدراج الكيانات

توفر العملية upsert طريقة ملائمة لإدراج أو تحديث الكيانات في مجموعة.

نظرة عامة

يمكنك استخدام upsert إما لإدراج كيان جديد أو تحديث كيان موجود، اعتمادًا على ما إذا كان المفتاح الأساسي المقدم في طلب الإدراج موجودًا في المجموعة. إذا لم يتم العثور على المفتاح الأساسي، تحدث عملية إدراج. خلاف ذلك، سيتم إجراء عملية تحديث.

يعمل الإدراج في Milvus إما في وضع التجاوز أو الدمج.

إدراج في وضع التجاوز

يجمع طلب upsert الذي يعمل في وضع التجاوز بين الإدراج والحذف. عندما يتم استلام طلب upsert لكيان موجود، يقوم Milvus بإدراج البيانات الموجودة في حمولة الطلب وحذف الكيان الموجود مع المفتاح الأساسي الأصلي المحدد في البيانات في نفس الوقت.

Upsert In Override Mode الإدراج في وضع التجاوز

إذا تم تمكين autoid في المجموعة المستهدفة على الحقل الأساسي الخاص بها، فسيقوم Milvus بإنشاء مفتاح أساسي جديد للبيانات المنقولة في حمولة الطلب قبل إدراجها.

بالنسبة للحقول التي تم تمكين nullable ، يمكنك حذفها في طلب upsert إذا كانت لا تتطلب أي تحديثات.

الإدراج في وضع الدمجCompatible with Milvus v2.6.2+

يمكنك أيضًا استخدام العلامة partial_update لجعل طلب الإضافة يعمل في وضع الدمج. يتيح لك ذلك تضمين الحقول التي تحتاج إلى تحديث فقط في حمولة الطلب.

Upsert In Merge Mode Upsert في وضع الدمج

لإجراء عملية دمج، قم بتعيين partial_update إلى True في طلب upsert مع المفتاح الأساسي والحقول المراد تحديثها بقيمها الجديدة.

عند تلقي مثل هذا الطلب، يقوم Milvus بإجراء استعلام بتناسق قوي لاسترداد الكيان، وتحديث قيم الحقول بناءً على البيانات الواردة في الطلب، وإدراج البيانات المعدلة، ثم حذف الكيان الحالي مع المفتاح الأساسي الأصلي المحمول في الطلب.

سلوكيات الإدراج: ملاحظات خاصة

هناك العديد من الملاحظات الخاصة التي يجب مراعاتها قبل استخدام ميزة الدمج. تفترض الحالات التالية أن لديك مجموعة تحتوي على حقلين قياسيين باسم title و issue ، إلى جانب مفتاح أساسي id وحقل متجه يسمى vector.

  • حقول Upsert مع تمكين nullable .

    افترض أن الحقل issue يمكن أن يكون فارغًا. عندما تقوم بإدراج هذه الحقول، لاحظ ذلك:

    • إذا قمت بحذف الحقل issue في الطلب upsert وتعطيل partial_update ، فسيتم تحديث الحقل issue إلى null بدلاً من الاحتفاظ بقيمته الأصلية.

    • للحفاظ على القيمة الأصلية للحقل issue ، تحتاج إما إلى تمكين partial_update وحذف الحقل issue أو تضمين الحقل issue بقيمته الأصلية في الطلب upsert.

  • رفع المفاتيح في الحقل الديناميكي.

    لنفترض أنك قمت بتمكين المفتاح الديناميكي في مجموعة الأمثلة، وكانت أزواج المفاتيح-القيم في الحقل الديناميكي لكيان ما مشابهة لـ {"author": "John", "year": 2020, "tags": ["fiction"]}.

    عند إعادة إدراج الكيان بمفاتيح، مثل author أو year أو أو tags أو إضافة مفاتيح أخرى، لاحظ ذلك:

    • إذا قمت بإعادة إدراج مع تعطيل partial_update ، فإن السلوك الافتراضي هو التجاوز. وهذا يعني أن قيمة الحقل الديناميكي سيتم تجاوزها من قبل جميع الحقول غير المعرفة من قبل المخطط المدرجة في الطلب وقيمها.

      على سبيل المثال، إذا كانت البيانات المضمنة في الطلب هي {"author": "Jane", "genre": "fantasy"} ، فسيتم تحديث أزواج المفاتيح-القيم في الحقل الديناميكي للكيان الهدف إلى ذلك.

    • إذا قمت بالإدراج مع تمكين partial_update ، فإن السلوك الافتراضي هو الدمج. ويعني ذلك أن قيمة الحقل الديناميكي سيتم دمجها مع جميع الحقول غير المحددة في النموذج المضمنة في الطلب وقيمها.

      على سبيل المثال، إذا كانت البيانات المضمنة في الطلب هي {"author": "John", "year": 2020, "tags": ["fiction"]} ، ستصبح أزواج المفاتيح-القيم في الحقل الديناميكي للكيان الهدف {"author": "John", "year": 2020, "tags": ["fiction"], "genre": "fantasy"} بعد عملية الإضافة.

  • إعادة إدراج حقل JSON.

    لنفترض أن مجموعة الأمثلة تحتوي على حقل JSON معرّف من قبل المخطط اسمه extras ، وأزواج القيمة الرئيسية في حقل JSON هذا في كيان ما مشابهة لـ {"author": "John", "year": 2020, "tags": ["fiction"]}.

    عندما تقوم بإدراج الحقل extras الخاص بكيان ما ببيانات JSON المعدلة، لاحظ أنه يتم التعامل مع حقل JSON ككل، ولا يمكنك تحديث المفاتيح الفردية بشكل انتقائي. وبعبارة أخرى، لا يدعم حقل JSON عملية الإدراج في وضع الدمج.

الحدود والقيود

بناءً على المحتوى أعلاه، هناك العديد من الحدود والقيود التي يجب اتباعها:

  • يجب أن يتضمن طلب upsert دائمًا المفاتيح الأساسية للكيانات المستهدفة.

  • يجب أن تكون المجموعة المستهدفة محملة ومتاحة للاستعلامات.

  • يجب أن تكون جميع الحقول المحددة في الطلب موجودة في مخطط المجموعة المستهدفة.

  • يجب أن تتطابق قيم جميع الحقول المحددة في الطلب مع أنواع البيانات المحددة في المخطط.

  • بالنسبة لأي حقل مشتق من حقل آخر باستخدام الدوال، سيقوم ميلفوس بإزالة الحقل المشتق أثناء عملية إعادة الإدراج للسماح بإعادة الحساب.

إعادة إدراج الكيانات في مجموعة

في هذا القسم، سنقوم بإدراج الكيانات في مجموعة تسمى my_collection. تحتوي هذه المجموعة على حقلين فقط باسم id و vector و title و issue. الحقل id هو الحقل الأساسي، بينما الحقلان title و issue هما حقلان قياسيان.

سيتم تجاوز الكيانات الثلاثة، إذا كانت موجودة في المجموعة، من قبل تلك التي يتضمنها طلب الإدراج.

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,
#         ]
#     }
# }

إدراج الكيانات في قسم

يمكنك أيضًا إدراج كيانات في قسم محدد. تفترض مقتطفات الشيفرة التالية أن لديك قسمًا باسم PartitionA في مجموعتك.

سيتم تجاوز الكيانات الثلاثة، إذا كانت موجودة في القسم، من قبل الكيانات المضمنة في الطلب.

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,
#         ]
#     }
# }

إدراج الكيانات في وضع الدمجCompatible with Milvus v2.6.2+

يوضّح المثال البرمجي التالي كيفية رفع إدراج الكيانات مع تحديثات جزئية. قم بتوفير الحقول التي تحتاج إلى تحديثات وقيمها الجديدة فقط، بالإضافة إلى علامة التحديث الجزئي الصريحة.

في المثال التالي، سيتم تحديث الحقل issue الخاص بالكيانات المحددة في طلب التحديث إلى القيم المضمنة في الطلب.

عند تنفيذ عملية إعادة إدراج في وضع الدمج، تأكد من أن الكيانات المتضمنة في الطلب لها نفس مجموعة الحقول. لنفترض أن هناك كيانين أو أكثر سيتم إدراجها، كما هو موضح في مقتطف الشيفرة التالي، من المهم أن تتضمن حقولًا متطابقة لمنع الأخطاء والحفاظ على تكامل البيانات.

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,
#         ]
#     }
# }