🚀 Coba Zilliz Cloud, Milvus yang sepenuhnya terkelola, secara gratis—rasakan performa 10x lebih cepat! Coba Sekarang>>

milvus-logo
LFAI
Beranda
  • Panduan Pengguna
  • Home
  • Docs
  • Panduan Pengguna

  • Bidang Skema & Data

  • Bidang JSON

Bidang JSON

JSON (JavaScript Object Notation) adalah format pertukaran data ringan yang menyediakan cara yang fleksibel untuk menyimpan dan menanyakan struktur data yang kompleks. Di Milvus, Anda dapat menyimpan informasi terstruktur tambahan di samping data vektor menggunakan bidang JSON, sehingga memungkinkan pencarian dan kueri tingkat lanjut yang menggabungkan kemiripan vektor dengan pemfilteran terstruktur.

Bidang JSON ideal untuk aplikasi yang memerlukan metadata untuk mengoptimalkan hasil pencarian. Misalnya, dalam e-commerce, vektor produk dapat ditingkatkan dengan atribut seperti kategori, harga, dan merek. Dalam sistem rekomendasi, vektor pengguna dapat digabungkan dengan preferensi dan informasi demografis. Di bawah ini adalah contoh bidang JSON yang umum.

{
  "category": "electronics",
  "price": 99.99,
  "brand": "BrandA"
}

Menambahkan bidang JSON

Untuk menggunakan bidang JSON di Milvus, tentukan jenis bidang yang relevan dalam skema koleksi, atur datatype ke jenis JSON yang didukung, misalnya, JSON.

Berikut ini cara mendefinisikan skema koleksi yang menyertakan bidang JSON.

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="http://localhost:19530")

schema = client.create_schema(
    auto_id=False,
    enable_dynamic_fields=True,
)

schema.add_field(field_name="metadata", datatype=DataType.JSON)
schema.add_field(field_name="pk", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="embedding", datatype=DataType.FLOAT_VECTOR, dim=3)

import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;

import io.milvus.v2.common.DataType;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;

MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
        .uri("http://localhost:19530")
        .build());
        
CreateCollectionReq.CollectionSchema schema = client.createSchema();
schema.setEnableDynamicField(true);

schema.addField(AddFieldReq.builder()
        .fieldName("metadata")
        .dataType(DataType.JSON)
        .build());

schema.addField(AddFieldReq.builder()
        .fieldName("pk")
        .dataType(DataType.Int64)
        .isPrimaryKey(true)
        .build());

schema.addField(AddFieldReq.builder()
        .fieldName("embedding")
        .dataType(DataType.FloatVector)
        .dimension(3)
        .build());

import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const schema = [
  {
    name: "metadata",
    data_type: DataType.JSON,
  },
  {
    name: "pk",
    data_type: DataType.Int64,
    is_primary_key: true,
  },
  {
    name: "embedding",
    data_type: DataType.FloatVector,
    dim: 3,
  },
];

export jsonField='{
    "fieldName": "metadata",
    "dataType": "JSON"
}'

export pkField='{
    "fieldName": "pk",
    "dataType": "Int64",
    "isPrimary": true
}'

export vectorField='{
    "fieldName": "embedding",
    "dataType": "FloatVector",
    "elementTypeParams": {
        "dim": 3
    }
}'

export schema="{
    \"autoID\": false,
    \"fields\": [
        $jsonField,
        $pkField,
        $vectorField
    ]
}"

Dalam contoh ini, kita menambahkan bidang JSON bernama metadata untuk menyimpan metadata tambahan yang terkait dengan data vektor, seperti kategori produk, harga, dan informasi merek.

Bidang utama dan bidang vektor wajib ada saat Anda membuat koleksi. Bidang utama mengidentifikasi setiap entitas secara unik, sedangkan bidang vektor sangat penting untuk pencarian kemiripan. Untuk lebih jelasnya, lihat Bidang Utama & AutoID, Vektor Padat, Vektor Biner, atau Vektor Jarang.

Membuat koleksi

Ketika membuat koleksi, Anda harus membuat indeks untuk bidang vektor untuk memastikan kinerja pengambilan. Dalam contoh ini, kami menggunakan AUTOINDEX untuk menyederhanakan penyiapan indeks. Untuk lebih jelasnya, lihat AUTOINDEX.


index_params = client.prepare_index_params()

index_params.add_index(
    field_name="embedding",
    index_type="AUTOINDEX",
    metric_type="COSINE"
)

import io.milvus.v2.common.IndexParam;
import java.util.*;

List<IndexParam> indexes = new ArrayList<>();
indexes.add(IndexParam.builder()
        .fieldName("embedding")
        .indexType(IndexParam.IndexType.AUTOINDEX)
        .metricType(IndexParam.MetricType.COSINE)
        .build());

const indexParams = {
    index_name: 'embedding_index',
    field_name: 'embedding',
    metricType: MetricType.CONSINE,
    index_type: IndexType.AUTOINDEX,
);

export indexParams='[
        {
            "fieldName": "embedding",
            "metricType": "COSINE",
            "indexType": "AUTOINDEX"
        }
    ]'

Gunakan skema yang ditentukan dan parameter indeks untuk membuat koleksi.

client.create_collection(
    collection_name="my_json_collection",
    schema=schema,
    index_params=index_params
)

CreateCollectionReq requestCreate = CreateCollectionReq.builder()
        .collectionName("my_json_collection")
        .collectionSchema(schema)
        .indexParams(indexes)
        .build();
client.createCollection(requestCreate);

client.create_collection({
    collection_name: "my_json_collection",
    schema: schema,
    index_params: indexParams
})

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
    \"collectionName\": \"my_json_collection\",
    \"schema\": $schema,
    \"indexParams\": $indexParams
}"

Menyisipkan data

Setelah membuat koleksi, Anda dapat menyisipkan data yang menyertakan bidang JSON.

# Data to be inserted
data = [
  {
      "metadata": {"category": "electronics", "price": 99.99, "brand": "BrandA"},
      "pk": 1,
      "embedding": [0.12, 0.34, 0.56]
  },
  {
      "metadata": {"category": "home_appliances", "price": 249.99, "brand": "BrandB"},
      "pk": 2,
      "embedding": [0.56, 0.78, 0.90]
  },
  {
      "metadata": {"category": "furniture", "price": 399.99, "brand": "BrandC"},
      "pk": 3,
      "embedding": [0.91, 0.18, 0.23]
  }
]

# Insert data into the collection
client.insert(
    collection_name="your_collection_name",
    data=data
)

import com.google.gson.Gson;
import com.google.gson.JsonObject;

import io.milvus.v2.service.vector.request.InsertReq;
import io.milvus.v2.service.vector.response.InsertResp;

List<JsonObject> rows = new ArrayList<>();
Gson gson = new Gson();
rows.add(gson.fromJson("{\"metadata\": {\"category\": \"electronics\", \"price\": 99.99, \"brand\": \"BrandA\"}, \"pk\": 1, \"embedding\": [0.1, 0.2, 0.3]}", JsonObject.class));
rows.add(gson.fromJson("{\"metadata\": {\"category\": \"home_appliances\", \"price\": 249.99, \"brand\": \"BrandB\"}, \"pk\": 2, \"embedding\": [0.4, 0.5, 0.6]}", JsonObject.class));
rows.add(gson.fromJson("{\"metadata\": {\"category\": \"furniture\", \"price\": 399.99, \"brand\": \"BrandC\"}, \"pk\": 3, \"embedding\": [0.7, 0.8, 0.9]}", JsonObject.class));

InsertResp insertR = client.insert(InsertReq.builder()
        .collectionName("my_json_collection")
        .data(rows)
        .build());

const data = [
  {
      "metadata": {"category": "electronics", "price": 99.99, "brand": "BrandA"},
      "pk": 1,
      "embedding": [0.12, 0.34, 0.56]
  },
  {
      "metadata": {"category": "home_appliances", "price": 249.99, "brand": "BrandB"},
      "pk": 2,
      "embedding": [0.56, 0.78, 0.90]
  },
  {
      "metadata": {"category": "furniture", "price": 399.99, "brand": "BrandC"},
      "pk": 3,
      "embedding": [0.91, 0.18, 0.23]
  }
]

client.insert({
    collection_name: "my_json_collection",
    data: data
});

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
    "data": [
        {
            "metadata": {"category": "electronics", "price": 99.99, "brand": "BrandA"},
            "pk": 1,
            "embedding": [0.12, 0.34, 0.56]
        },
        {
            "metadata": {"category": "home_appliances", "price": 249.99, "brand": "BrandB"},
            "pk": 2,
            "embedding": [0.56, 0.78, 0.90]
        },
        {
            "metadata": {"category": "furniture", "price": 399.99, "brand": "BrandC"},
            "pk": 3,
            "embedding": [0.91, 0.18, 0.23]
        }       
    ],
    "collectionName": "my_json_collection"
}'

Dalam contoh ini.

  • Setiap entri data mencakup bidang utama (pk), metadata sebagai bidang JSON untuk menyimpan informasi seperti kategori produk, harga, dan merek.

  • embedding adalah bidang vektor 3 dimensi yang digunakan untuk pencarian kemiripan vektor.

Pencarian dan kueri

Bidang JSON memungkinkan pemfilteran skalar selama pencarian, meningkatkan kemampuan pencarian vektor Milvus. Anda dapat membuat kueri berdasarkan properti JSON di samping kemiripan vektor.

Menyaring kueri

Anda dapat memfilter data berdasarkan properti JSON, seperti mencocokkan nilai tertentu atau memeriksa apakah suatu angka berada dalam rentang tertentu.

filter = 'metadata["category"] == "electronics" and metadata["price"] < 150'

res = client.query(
    collection_name="my_json_collection",
    filter=filter,
    output_fields=["metadata"]
)

print(res)

# Output
# data: ["{'metadata': {'category': 'electronics', 'price': 99.99, 'brand': 'BrandA'}, 'pk': 1}"] 

import io.milvus.v2.service.vector.request.QueryReq;
import io.milvus.v2.service.vector.response.QueryResp;

String filter = "metadata[\"category\"] == \"electronics\" and metadata[\"price\"] < 150";
QueryResp resp = client.query(QueryReq.builder()
        .collectionName("my_json_collection")
        .filter(filter)
        .outputFields(Collections.singletonList("metadata"))
        .build());

System.out.println(resp.getQueryResults());

// Output
//
// [QueryResp.QueryResult(entity={metadata={"category":"electronics","price":99.99,"brand":"BrandA"}, pk=1})]

client.query({
    collection_name: 'my_scalar_collection',
    filter: 'metadata["category"] == "electronics" and metadata["price"] < 150',
    output_fields: ['metadata']
});

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
    "collectionName": "my_json_collection",
    "filter": "metadata[\"category\"] == \"electronics\" and metadata[\"price\"] < 150",
    "outputFields": ["metadata"]
}'
{"code":0,"cost":0,"data":[{"metadata":"{\"category\": \"electronics\", \"price\": 99.99, \"brand\": \"BrandA\"}","pk":1}]}

Pada kueri di atas, Milvus menyaring entitas dengan bidang metadata yang memiliki kategori "electronics" dan harga di bawah 150, dan mengembalikan entitas yang sesuai dengan kriteria ini.

Pencarian vektor dengan pemfilteran JSON

Dengan menggabungkan kemiripan vektor dengan pemfilteran JSON, Anda dapat memastikan bahwa data yang diambil tidak hanya cocok secara semantik tetapi juga memenuhi kondisi bisnis tertentu, sehingga hasil pencarian lebih tepat dan selaras dengan kebutuhan pengguna.

filter = 'metadata["brand"] == "BrandA"'

res = client.search(
    collection_name="my_json_collection",
    data=[[0.3, -0.6, 0.1]],
    limit=5,
    search_params={"params": {"nprobe": 10}},
    output_fields=["metadata"],
    filter=filter
)

print(res)

# Output
# data: ["[{'id': 1, 'distance': -0.2479381263256073, 'entity': {'metadata': {'category': 'electronics', 'price': 99.99, 'brand': 'BrandA'}}}]"] 

import io.milvus.v2.service.vector.request.SearchReq;
import io.milvus.v2.service.vector.response.SearchResp;

String filter = "metadata[\"brand\"] == \"BrandA\"";
SearchResp resp = client.search(SearchReq.builder()
        .collectionName("my_json_collection")
        .annsField("embedding")
        .data(Collections.singletonList(new FloatVec(new float[]{0.3f, -0.6f, 0.1f})))
        .topK(5)
        .outputFields(Collections.singletonList("metadata"))
        .filter(filter)
        .build());

System.out.println(resp.getSearchResults());

// Output
//
// [[SearchResp.SearchResult(entity={metadata={"category":"electronics","price":99.99,"brand":"BrandA"}}, score=-0.2364331, id=1)]]

client.search({
    collection_name: 'my_json_collection',
    data: [0.3, -0.6, 0.1],
    limit: 5,
    output_fields: ['metadata'],
    filter: 'metadata["category"] == "electronics" and metadata["price"] < 150',
});

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
    "collectionName": "my_json_collection",
    "data": [
        [0.3, -0.6, 0.1]
    ],
    "annsField": "embedding",
    "limit": 5,
    "searchParams":{
        "params":{"nprobe":10}
    },
    "outputFields": ["metadata"],
    "filter": "metadata[\"brand\"] == \"BrandA\""
}'

## {"code":0,"cost":0,"data":[{"distance":-0.24793813,"id":1,"metadata":"{\"category\": \"electronics\", \"price\": 99.99, \"brand\": \"BrandA\"}"}]}

Dalam contoh ini, Milvus mengembalikan 5 entitas teratas yang paling mirip dengan vektor kueri, dengan bidang metadata yang berisi merek "BrandA".

Selain itu, Milvus mendukung operator pemfilteran JSON tingkat lanjut seperti JSON_CONTAINS, JSON_CONTAINS_ALL, dan JSON_CONTAINS_ANY, yang dapat meningkatkan kemampuan kueri lebih lanjut. Untuk lebih jelasnya, lihat Pemfilteran Metadata.

Batasan

  • Batasan Pengindeksan: Karena kompleksitas struktur data, pengindeksan bidang JSON tidak didukung.

  • Pencocokan Tipe Data: Jika nilai kunci bidang JSON berupa bilangan bulat atau titik mengambang, nilai tersebut hanya dapat dibandingkan dengan kunci bilangan bulat atau mengambang lainnya atau bidang INT32/64 atau FLOAT32/64. Jika nilai kunci berupa string (VARCHAR), maka hanya dapat dibandingkan dengan kunci string lainnya.

  • Batasan Penamaan: Ketika menamai kunci JSON, disarankan untuk hanya menggunakan huruf, karakter numerik, dan garis bawah, karena karakter lain dapat menyebabkan masalah saat pemfilteran atau pencarian.

  • Menangani Nilai String: Untuk nilai string (VARCHAR), Milvus menyimpan string bidang JSON apa adanya tanpa konversi semantik. Sebagai contoh 'a"b', "a'b", 'a\\'b', dan "a\\"b" disimpan seperti yang dimasukkan; namun, 'a'b' dan "a"b" dianggap tidak valid.

  • Menangani Kamus Bersarang: Setiap kamus bertingkat dalam nilai bidang JSON diperlakukan sebagai string.

  • Batas Ukuran Bidang JSON: Bidang JSON dibatasi hingga 65.536 byte.

Coba Milvus yang Dikelola secara Gratis

Zilliz Cloud bebas masalah, didukung oleh Milvus dan 10x lebih cepat.

Mulai
Umpan balik

Apakah halaman ini bermanfaat?