Mengaktifkan Bidang Dinamis
Halaman ini menjelaskan cara menggunakan bidang dinamis dalam koleksi untuk penyisipan dan pengambilan data yang fleksibel.
Gambaran Umum
Milvus memungkinkan Anda untuk mendefinisikan skema koleksi dengan mengatur nama dan tipe data dari setiap bidang tertentu sehingga Anda dapat membuat indeks dalam bidang ini untuk meningkatkan kinerja pencarian.
Setelah sebuah field didefinisikan, Anda harus menyertakan field ini ketika Anda memasukkan data. Bagaimana jika beberapa field tidak selalu ada di semua entri data Anda? Di sinilah bidang dinamis berperan.
Bidang dinamis dalam koleksi adalah bidang JSON yang dicadangkan bernama $meta. Bidang ini dapat menampung bidang yang tidak ditentukan skema dan nilainya sebagai pasangan kunci-nilai. Dengan menggunakan bidang dinamis, Anda dapat mencari dan menanyakan bidang yang ditentukan skema dan bidang yang tidak ditentukan skema yang mungkin dimilikinya.
Mengaktifkan bidang dinamis
Ketika mendefinisikan skema untuk koleksi, Anda dapat mengatur enable_dynamic_field ke True untuk mengaktifkan bidang dinamis yang dicadangkan, yang mengindikasikan bahwa semua bidang yang tidak ditentukan skema dan nilainya yang dimasukkan nanti akan disimpan sebagai pasangan kunci-nilai di bidang dinamis yang dicadangkan.
Cuplikan berikut ini membuat koleksi dengan dua field yang ditentukan skema, yaitu id dan vektor, dan mengaktifkan field dinamis.
Untuk informasi lebih lanjut tentang parameter, lihat create_collection() dalam referensi SDK.
Untuk informasi lebih lanjut tentang parameter, lihat createCollection() dalam referensi SDK.
Untuk informasi lebih lanjut tentang parameter, lihat createCollection() dalam referensi SDK.
import random, time
from pymilvus import connections, MilvusClient, DataType
SERVER_ADDR = "http://localhost:19530"
# 1. Set up a Milvus client
client = MilvusClient(
uri=SERVER_ADDR
)
# 2. Create a collection
schema = MilvusClient.create_schema(
auto_id=False,
enable_dynamic_field=True,
)
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5)
index_params = MilvusClient.prepare_index_params()
index_params.add_index(
field_name="id",
index_type="STL_SORT"
)
index_params.add_index(
field_name="vector",
index_type="IVF_FLAT",
metric_type="L2",
params={"nlist": 1024}
)
client.create_collection(
collection_name="test_collection",
schema=schema,
index_params=index_params
)
res = client.get_load_state(
collection_name="test_collection"
)
print(res)
# Output
#
# {
# "state": "<LoadState: Loaded>"
# }
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.common.DataType;
import io.milvus.v2.common.IndexParam;
import io.milvus.v2.service.collection.request.*;
import io.milvus.v2.service.vector.request.*;
import io.milvus.v2.service.vector.request.data.*;
import io.milvus.v2.service.vector.response.*;
import java.util.*;
String CLUSTER_ENDPOINT = "http://localhost:19530";
// 1. Connect to Milvus server
ConnectConfig connectConfig = ConnectConfig.builder()
.uri(CLUSTER_ENDPOINT)
.build();
MilvusClientV2 client = new MilvusClientV2(connectConfig);
// 2. Create a collection in customized setup mode
// 2.1 Create schema
CreateCollectionReq.CollectionSchema schema = client.createSchema();
schema.setEnableDynamicField(true);
// 2.2 Add fields to schema
schema.addField(AddFieldReq.builder().fieldName("id").dataType(DataType.Int64).isPrimaryKey(true).autoID(false).build());
schema.addField(AddFieldReq.builder().fieldName("vector").dataType(DataType.FloatVector).dimension(5).build());
// 2.3 Prepare index parameters
IndexParam indexParamForIdField = IndexParam.builder()
.fieldName("id")
.indexType(IndexParam.IndexType.STL_SORT)
.build();
Map<String, Object> params = new HashMap<>();
params.put("nlist", 1024);
IndexParam indexParamForVectorField = IndexParam.builder()
.fieldName("vector")
.indexType(IndexParam.IndexType.IVF_FLAT)
.metricType(IndexParam.MetricType.IP)
.extraParams(params)
.build();
List<IndexParam> indexParams = new ArrayList<>();
indexParams.add(indexParamForIdField);
indexParams.add(indexParamForVectorField);
// 2.4 Create a collection with schema and index parameters
CreateCollectionReq customizedSetupReq = CreateCollectionReq.builder()
.collectionName("customized_setup")
.collectionSchema(schema)
.indexParams(indexParams)
.build();
client.createCollection(customizedSetupReq);
Thread.sleep(5000);
// 2.5 Get load state of the collection
GetLoadStateReq customSetupLoadStateReq1 = GetLoadStateReq.builder()
.collectionName("customized_setup")
.build();
boolean res = client.getLoadState(customSetupLoadStateReq1);
System.out.println(res);
// Output:
// true
const { MilvusClient, DataType, sleep } = require("@zilliz/milvus2-sdk-node")
const address = "http://localhost:19530"
async function main() {
// 1. Set up a Milvus Client
client = new MilvusClient({address});
// 2. Create a collection
// 2.1 Define fields
const fields = [
{
name: "id",
data_type: DataType.Int64,
is_primary_key: true,
auto_id: false
},
{
name: "vector",
data_type: DataType.FloatVector,
dim: 5
},
]
// 2.2 Prepare index parameters
const index_params = [{
field_name: "id",
index_type: "STL_SORT"
},{
field_name: "vector",
index_type: "IVF_FLAT",
metric_type: "IP",
params: { nlist: 1024}
}]
// 2.3 Create a collection with fields and index parameters
res = await client.createCollection({
collection_name: "test_collection",
fields: fields,
index_params: index_params,
enable_dynamic_field: true
})
console.log(res.error_code)
// Output
//
// Success
//
res = await client.getLoadState({
collection_name: "test_collection",
})
console.log(res.state)
// Output
//
// LoadStateLoaded
//
Menyisipkan data dinamis
Setelah koleksi dibuat, Anda dapat mulai menyisipkan data, termasuk data dinamis ke dalam koleksi.
Menyiapkan data
Pada bagian ini, Anda perlu menyiapkan beberapa data yang dibuat secara acak untuk penyisipan nanti.
colors = ["green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey"]
data = []
for i in range(1000):
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])
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();
Random rand = new Random();
for (int i=0; i<1000; i++) {
String current_color = colors.get(rand.nextInt(colors.size()-1));
int current_tag = rand.nextInt(8999) + 1000;
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", current_color);
row.addProperty("tag", current_tag);
row.addProperty("color_tag", current_color + "_" + (rand.nextInt(8999) + 1000));
data.add(row);
}
System.out.println(data.get(0).toString());
const colors = ["green", "blue", "yellow", "red", "black", "white", "purple", "pink", "orange", "brown", "grey"]
var data = []
for (let i = 0; i < 1000; i++) {
const current_color = colors[Math.floor(Math.random() * colors.length)]
const current_tag = Math.floor(Math.random() * 8999 + 1000)
data.push({
id: i,
vector: [Math.random(), Math.random(), Math.random(), Math.random(), Math.random()],
color: current_color,
tag: current_tag,
color_tag: `${current_color}_${current_tag}`
})
}
console.log(data[0])
Anda dapat melihat struktur data yang dihasilkan dengan memeriksa entri pertamanya.
{
id: 0,
vector: [
0.1275656405044483,
0.47417858592773277,
0.13858264437643286,
0.2390904907020377,
0.8447862593689635
],
color: 'blue',
tag: 2064,
color_tag: 'blue_2064'
}
Memasukkan data
Kemudian Anda dapat dengan aman memasukkan data ke dalam koleksi.
Untuk informasi lebih lanjut tentang parameter, lihat insert() dalam referensi SDK.
Untuk informasi lebih lanjut tentang parameter, lihat insert() dalam referensi SDK.
Untuk informasi lebih lanjut tentang parameter, lihat insert() dalam referensi SDK.
res = client.insert(
collection_name="test_collection",
data=data,
)
print(res)
# Output
#
# {
# "insert_count": 1000,
# "ids": [
# 0,
# 1,
# 2,
# 3,
# 4,
# 5,
# 6,
# 7,
# 8,
# 9,
# "(990 more items hidden)"
# ]
# }
time.sleep(5)
// 3.1 Insert data into the collection
InsertReq insertReq = InsertReq.builder()
.collectionName("customized_setup")
.data(data)
.build();
InsertResp insertResp = client.insert(insertReq);
System.out.println(insertResp.getInsertCnt());
// Output:
// 1000
Thread.sleep(5000);
res = await client.insert({
collection_name: "test_collection",
data: data,
})
console.log(res.insert_cnt)
// Output
//
// 1000
//
await sleep(5000)
Mencari dengan bidang dinamis
Jika Anda telah membuat koleksi dengan bidang dinamis diaktifkan dan menyisipkan bidang yang tidak ditentukan skema, Anda dapat menggunakan bidang ini dalam ekspresi filter pencarian atau kueri sebagai berikut.
Untuk informasi lebih lanjut tentang parameter, lihat search() di referensi SDK.
Untuk informasi lebih lanjut tentang parameter, lihat search() dalam referensi SDK.
Untuk informasi lebih lanjut tentang parameter, lihat search() dalam referensi SDK.
# 4. Search with dynamic fields
query_vectors = [[0.3580376395471989, -0.6023495712049978, 0.18414012509913835, -0.26286205330961354, 0.9029438446296592]]
res = client.search(
collection_name="test_collection",
data=query_vectors,
filter="color in [\"red\", \"green\"]",
search_params={"metric_type": "L2", "params": {"nprobe": 10}},
limit=3
)
print(res)
# Output
#
# [
# [
# {
# "id": 863,
# "distance": 0.188413605093956,
# "entity": {
# "id": 863,
# "color_tag": "red_2371"
# }
# },
# {
# "id": 799,
# "distance": 0.29188022017478943,
# "entity": {
# "id": 799,
# "color_tag": "red_2235"
# }
# },
# {
# "id": 564,
# "distance": 0.3492690920829773,
# "entity": {
# "id": 564,
# "color_tag": "red_9186"
# }
# }
# ]
# ]
// 4. Search with non-schema-defined fields
List<BaseVector> queryVectors = Collections.singletonList(new FloatVec(new float[]{0.3580376395471989f, -0.6023495712049978f, 0.18414012509913835f, -0.26286205330961354f, 0.9029438446296592f}));
SearchReq searchReq = SearchReq.builder()
.collectionName("customized_setup")
.data(queryVectors)
.filter("$meta[\"color\"] in [\"red\", \"green\"]")
.outputFields(Arrays.asList("id", "color_tag"))
.topK(3)
.build();
SearchResp searchResp = client.search(searchReq);
List<List<SearchResp.SearchResult>> searchResults = searchResp.getSearchResults();
for (List<SearchResp.SearchResult> results : searchResults) {
System.out.println("TopK results:");
for (SearchResp.SearchResult result : results) {
System.out.println(result);
}
}
// Output:
// SearchResp.SearchResult(entity={color_tag=green_2205, id=556}, score=1.134007, id=556)
// SearchResp.SearchResult(entity={color_tag=red_2786, id=310}, score=0.9072295, id=310)
// SearchResp.SearchResult(entity={color_tag=red_9493, id=215}, score=0.8819287, id=215)
// 4. Search with non-schema-defined fields
const query_vectors = [[0.1, 0.2, 0.3, 0.4, 0.5]]
res = await client.search({
collection_name: "test_collection",
data: query_vectors,
filter: "color in [\"red\", \"green\"]",
output_fields: ["color_tag"],
limit: 3
})
console.log(res.results)
// Output
//
// [
// { score: 1.2284551858901978, id: '301', color_tag: 'red_1270' },
// { score: 1.2195171117782593, id: '205', color_tag: 'red_2780' },
// { score: 1.2055039405822754, id: '487', color_tag: 'red_6653' }
// ]
//
Rangkuman
Perlu dicatat bahwa color, tag, dan color_tag tidak ada ketika Anda mendefinisikan skema koleksi, tetapi Anda dapat menggunakannya sebagai bidang yang ditentukan skema ketika Anda melakukan pencarian dan kueri.
Jika nama bidang yang tidak ditentukan skema berisi karakter selain angka, huruf, dan garis bawah, seperti tanda tambah (+), tanda bintang (*), atau tanda dolar (), Anda harus menyertakan kunci di dalam __meta[]__ seperti yang ditunjukkan pada cuplikan kode berikut ini ketika menggunakannya dalam ekspresi boolean atau menyertakannya di dalam bidang keluaran.
...
filter='$meta["$key"] in ["a", "b", "c"]',
output_fields='$meta["$key"]'
...