JSON 欄位概述
在建立商品目錄、內容管理系統或使用者偏好引擎等應用程式時,您通常需要在向量嵌入的同時儲存彈性的元資料。產品屬性因類別而異,使用者偏好隨時間演變,而文件屬性則有複雜的嵌套結構。Milvus 的 JSON 欄位可讓您在不犧牲效能的情況下,儲存和查詢彈性的結構化資料,從而解決這項挑戰。
什麼是 JSON 欄位?
在 Milvus 中,JSON 欄位是一種模式定義的資料類型 (DataType.JSON) ,用來儲存結構化的鍵值資料。與傳統僵化的資料庫列不同,JSON 欄位可容納巢狀物件、陣列和混合資料類型,同時提供多種索引選項以進行快速查詢。
JSON 欄位結構範例:
{
"metadata": {
"category": "electronics",
"brand": "BrandA",
"in_stock": true,
"price": 99.99,
"string_price": "99.99",
"tags": ["clearance", "summer_sale"],
"supplier": {
"name": "SupplierX",
"country": "USA",
"contact": {
"email": "support@supplierx.com",
"phone": "+1-800-555-0199"
}
}
}
}
在這個範例中,metadata 是一個單一的 JSON 欄位,包含平面值 (例如category,in_stock)、陣列 (tags) 和巢狀物件 (supplier) 的混合資料。
命名慣例:在 JSON 鍵中只使用字母、數字和底線。避免使用特殊字符、空格或點,因為它們可能會在查詢中導致解析問題。
JSON 欄位 vs. 動態欄位
常見的混淆點是 JSON 欄位與動態欄位之間的差異。雖然兩者都與 JSON 有關,但它們有不同的目的。
下表總結了 JSON 欄位與動態欄位之間的主要差異:
特徵 |
JSON 欄位 |
動態欄位 |
|---|---|---|
模式定義 |
一個標量欄位,必須在集合模式中以 |
一個隱藏的 JSON 欄位 (命名為 |
使用情況 |
儲存模式已知且一致的結構化資料。 |
儲存不符合固定模式的彈性、演進或半結構化資料。 |
控制 |
您可以控制欄位名稱和結構。 |
系統管理未定義的欄位。 |
查詢 |
使用您的欄位名稱或 JSON 欄位內的目標關鍵查詢: |
直接使用動態欄位關鍵查詢: |
基本操作
使用 JSON 欄位的基本工作流程包括在模式中定義、插入資料,然後透過特定的篩選表達式查詢資料。
定義 JSON 欄位
要使用 JSON 欄位,請在建立集合時,在集合模式中明確定義。下面的示例演示了如何使用metadata 欄位類型DataType.JSON 來創建一個集合:
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530") # Replace with your server address
# Create schema
schema = client.create_schema(auto_id=False, enable_dynamic_field=True)
schema.add_field(field_name="product_id", datatype=DataType.INT64, is_primary=True) # Primary field
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5) # Vector field
# Define a JSON field that allows null values
schema.add_field(field_name="metadata", datatype=DataType.JSON, nullable=True)
client.create_collection(
collection_name="product_catalog",
schema=schema
)
在這個範例中,在集合模式中定義的 JSON 欄位允許使用nullable=True 的 null 值。詳情請參閱Nullable & Default。
插入資料
建立資料集後,在指定的 JSON 欄位中插入包含結構化 JSON 物件的實體。您的資料格式應為字典清單。
entities = [
{
"product_id": 1,
"vector": [0.1, 0.2, 0.3, 0.4, 0.5],
"metadata": { # JSON field
"category": "electronics",
"brand": "BrandA",
"in_stock": True,
"price": 99.99,
"string_price": "99.99",
"tags": ["clearance", "summer_sale"],
"supplier": {
"name": "SupplierX",
"country": "USA",
"contact": {
"email": "support@supplierx.com",
"phone": "+1-800-555-0199"
}
}
}
}
]
client.insert(collection_name="product_catalog", data=entities)
過濾作業
在您對 JSON 欄位執行過濾作業之前,請確定
您已在每個向量欄位上建立索引。
集合已載入記憶體。
index_params = client.prepare_index_params()
index_params.add_index(
field_name="vector",
index_type="AUTOINDEX",
index_name="vector_index",
metric_type="COSINE"
)
client.create_index(collection_name="product_catalog", index_params=index_params)
client.load_collection(collection_name="product_catalog")
一旦滿足這些要求,您就可以使用下面的表達式,根據 JSON 欄位內的值對集合進行篩選。這些篩選表達式利用特定的 JSON 路徑語法和專用運算符號。
使用 JSON 路徑語法篩選
若要查詢特定的鍵,請使用括號符號存取 JSON 鍵:json_field_name["key"] 。對於嵌套的鍵,請將它們鏈結在一起:json_field_name["key1"]["key2"] 。
要過濾category 為"electronics" 的實體:
# Define filter expression
filter = 'metadata["category"] == "electronics"'
client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
要篩選嵌套鍵supplier["country"] 是"USA" 的實體:
# Define filter expression
filter = 'metadata["supplier"]["country"] == "USA"'
res = client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
print(res)
使用 JSON 特定的運算符號過濾
Milvus 也提供特殊的運算符號來查詢特定 JSON 欄位鍵的陣列值。例如
json_contains(identifier, expr):檢查 JSON 陣列中是否存在特定元素或子陣列json_contains_all(identifier, expr):確保指定的 JSON 表達式的所有元素都存在於欄位中json_contains_any(identifier, expr):過濾至少有一個 JSON 表達式成員存在於欄位中的實體
尋找在tags 鍵下有"summer_sale" 值的產品:
# Define filter expression
filter = 'json_contains(metadata["tags"], "summer_sale")'
res = client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
print(res)
尋找在tags 鍵下至少有一個"electronics","new", 或"clearance" 值的產品:
# Define filter expression
filter = 'json_contains_any(metadata["tags"], ["electronics", "new", "clearance"])'
res = client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
print(res)
有關 JSON 特定運算符號的詳細資訊,請參閱JSON 運算符號。
下一步:加速 JSON 查詢
預設情況下,在沒有加速的情況下,對 JSON 欄位的查詢會對所有行執行完整掃描,這在大型資料集上可能會很慢。為了加速 JSON 查詢,Milvus 提供了先進的索引和儲存優化功能。
下表總結了它們的差異和最佳使用情境:
技術 |
最適用於 |
陣列 加速 |
注意事項 |
|---|---|---|---|
JSON 索引 |
一小組經常存取的鍵,特定陣列鍵上的陣列 |
是(在索引陣列鍵上) |
必須預先選擇鍵,如果模式演進則需要維護 |
JSON 切碎 |
在多個鍵值上普遍加速,可彈性處理各種查詢 |
否(不會加速陣列內的值) |
額外的儲存配置,陣列仍需要每個鍵的索引 |
NGRAM 索引 |
通配符搜尋、文字欄位中的子串匹配 |
不適用 |
不適用於數值/範圍篩選器 |
提示:您可以結合這些方法--例如,使用 JSON 切碎來加速廣泛的查詢,使用 JSON 索引來處理高頻陣列鍵,使用 NGRAM 索引來處理彈性的文字搜尋。
如需實施細節,請參閱:
常見問題
JSON 欄位的大小有任何限制嗎?
有。每個 JSON 欄位的大小限制為 65,536 位元組。
JSON 欄位是否支援設定預設值?
不,JSON 欄位不支援預設值。但是,您可以在定義欄位時設定nullable=True ,以允許空項目。
詳情請參閱Nullable & Default。
JSON 欄位鍵有任何命名慣例嗎?
有,以確保與查詢和索引的相容性:
在 JSON 鍵中只使用字母、數字和底線。
避免使用特殊字符、空格或點 (
.,/, 等等)。不相容的鍵可能會在篩選表達式中造成解析問題。
Milvus 如何處理 JSON 欄位中的字串值?
Milvus 完全按照 JSON 輸入中出現的字串值來儲存,沒有語義轉換。引號不當的字串可能會在解析過程中導致錯誤。
有效字串的範例:
"a\"b", "a'b", "a\\b"
無效字串的範例:
'a"b', 'a\'b'