JSON フィールドの概要
商品カタログ、コンテンツ管理システム、ユーザープリファレンスエンジンなどのアプリケーションを構築する際、ベクトル埋め込みデータとともに柔軟なメタデータを保存する必要がよくあります。商品属性はカテゴリごとに異なり、ユーザーの好みは時間とともに変化し、ドキュメントのプロパティは複雑な入れ子構造を持つことがあります。Zilliz Cloud の JSON フィールドは、このような課題を解決します。柔軟な構造化データをパフォーマンスを犠牲にすることなく保存・クエリできるようにします。
JSON フィールドとは?
JSON フィールドとは、Zilliz Cloud におけるスキーマ定義済みのデータ型(データType.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 はフラットな値(例:category、in_stock)、配列(tags)、およびネストされたオブジェクト(supplier)を含む単一の JSON フィールドです。
命名規則:JSON キーには英字、数字、アンダースコアのみを使用してください。特殊文字、スペース、ドットはクエリでのパースエラーを引き起こす可能性があるため避けてください。
JSON フィールドと動的フィールド
よく混同されるのが、JSON フィールドと動的フィールドの違いです。どちらも JSON に関連していますが、目的は異なります。
以下の表は、JSON フィールドと動的フィールドの主な違いをまとめたものです:
機能 | JSON フィールド | 動的フィールド |
|---|---|---|
スキーマ定義 |
| 未宣言フィールドを自動的に格納する非表示の JSON フィールド( |
ユースケース | スキーマが既知かつ一貫性のある構造化データを格納。 | 固定スキーマに合わない柔軟で進化する、または半構造化されたデータを格納。 |
制御 | フィールド名と構造をユーザーが制御。 | 未定義フィールドに対してシステムが管理。 |
クエリ | フィールド名または JSON フィールド内のターゲットキーを使用してクエリ: | 動的フィールドキーを直接使用してクエリ: |
基本操作
JSON フィールドを使用する基本的なワークフローは、スキーマで定義し、データを挿入し、特定のフィルター式を使用してデータをクエリすることです。
JSON フィールドの定義
JSON フィールドを使用するには、コレクション作成時にコレクションスキーマで明示的に定義します。以下の例は、データType.JSON 型の metadata フィールドを持つコレクションを作成する方法を示しています:
- Python
- Java
- NodeJS
- Go
- cURL
from pymilvus import MilvusClient, DataType
CLUSTER_ENDPOINT = "YOUR_CLUSTER_ENDPOINT"
TOKEN = "YOUR_CLUSTER_TOKEN"
# Set up a Milvus client
client = MilvusClient(
uri=CLUSTER_ENDPOINT,
token=TOKEN
)
# 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
)
// java
// js
// go
# restful
この例では、コレクションスキーマで定義されたJSONフィールドが nullable=True により NULL許容 値を許可しています。詳細については、NULL許容 & デフォルト を参照してください。
Insert data
コレクションが作成されたら、指定したJSONフィールドに構造化されたJSONオブジェクトを含むエンティティを挿入します。データは辞書のリストとしてフォーマットする必要があります。
- Python
- Java
- NodeJS
- Go
- cURL
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)
// java
// js
// go
# restful
フィルタリング操作
JSONフィールドに対してフィルタリング操作を実行する前に、以下の点を確認してください:
-
各ベクトルフィールドにインデックスを作成済みであること。
-
コレクションがメモリにロード済みであること。
コード例を表示
- Python
- Java
- NodeJS
- Go
- cURL
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")
// java
// js
// go
# restful
これらの要件を満たせば、JSONフィールド内の値に基づいてコレクションをフィルタリングするための以下の式を使用できます。これらのフィルター式は、特定のJSONパス構文と専用の演算子を活用します。
JSONパス構文によるフィルタリング
特定のキーをクエリするには、角括弧表記を使用してJSONキーにアクセスします:json_field_name["key"]。ネストされたキーの場合は、それらを連鎖させます:json_field_name["key1"]["key2"]。
categoryが"electronics"であるエンティティをフィルタリングするには:
- Python
- Java
- NodeJS
- Go
- cURL
# 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
)
// java
// js
// go
# restful
ネストされたキー supplier["country"] が "USA" であるエンティティをフィルタリングするには:
- Python
- Java
- NodeJS
- Go
- cURL
# 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)
// java
// js
// go
# restful
JSON固有の演算子によるフィルター
Zilliz Cloud は、特定の JSON フィールドキーに対して配列値をクエリするための特殊な演算子も提供しています。例:
-
json_contains(identifier, expr): JSON 配列内に特定の要素またはサブ配列が存在するかどうかをチェックします。 -
json_contains_all(identifier, expr): 指定された JSON 式のすべての要素がフィールド内に存在することを保証します。 -
json_contains_any(identifier, expr): JSON 式のメンバーの少なくとも 1 つがフィールド内に存在するエンティティをフィルターします。
tags キーの下に "summer_sale" 値を持つ商品を検索するには:
- Python
- Java
- NodeJS
- Go
- cURL
# 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)
// java
// js
// go
# restful
tags キーの下に "electronics"、"new"、または "clearance" のいずれか少なくとも 1 つの値を持つ製品を検索するには:
- Python
- Java
- NodeJS
- Go
- cURL
# 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)
// java
// js
// go
# restful
JSON固有の演算子について詳しくは、JSON演算子を参照してください。
次のステップ: JSONクエリの高速化
デフォルトでは、高速化されていないJSONフィールドに対するクエリはすべての行をフルスキャンするため、大規模なデータセットでは遅くなる可能性があります。JSONクエリを高速化するために、Zilliz Cloudは高度なインデックス作成およびストレージ最適化機能を提供しています。
以下の表は、各手法の違いと最適な使用シナリオをまとめたものです:
手法 | 最適な用途 | 配列の高速化 | 備考 |
|---|---|---|---|
JSONインデックス | 頻繁にアクセスされる少数のキー、特定の配列キー上の配列 | はい(インデックスされた配列キー上) | 事前にキーを選択する必要があり、スキーマが変更された場合はメンテナンスが必要 |
JSONシュレッディング | 多数のキーにわたる一般的な高速化、多様なクエリに柔軟に対応 | はい(ブルートフォースクエリと比べて配列値を若干高速化) | 追加のストレージ設定が必要、配列には依然としてキーごとのインデックスが必要 |
NGRAMインデックス | ワイルドカード検索、テキストフィールド内の部分文字列マッチング | 該当なし | 数値フィルターや範囲フィルターには使用不可 |
ヒント: これらの手法を組み合わせることも可能です。例えば、広範なクエリの高速化にはJSONシュレッディングを、高頻度でアクセスされる配列キーにはJSONインデックスを、柔軟なテキスト検索にはNGRAMインデックスを使用できます。
実装の詳細については、以下を参照してください:
よくある質問(FAQ)
JSONフィールドのサイズに制限はありますか?
はい。各JSONフィールドは65,536バイトまでです。
JSONフィールドにデフォルト値を設定できますか?
いいえ、JSONフィールドはデフォルト値をサポートしていません。ただし、フィールド定義時に nullable=True を設定することで、空のエントリを許容できます。
詳細については、NULL許容 & デフォルトを参照してください。
JSONフィールドのキーには命名規則がありますか?
はい。クエリやインデックス作成との互換性を確保するため、以下の点に注意してください:
-
JSONキーには英数字とアンダースコアのみを使用してください。
-
特殊文字、スペース、ドット(
.や/など)は使用しないでください。 -
互換性のないキーは、フィルター式のパース時に問題を引き起こす可能性があります。
Zilliz CloudはJSONフィールド内の文字列値をどのように扱いますか?
Zilliz Cloudは、JSON入力に記述されたとおりに文字列値をそのまま保存し、意味的な変換は行いません。不適切にクォートされた文字列は、パース中にエラーを引き起こす可能性があります。
有効な文字列の例:
"a\"b", "a'b", "a\\b"
無効な文字列の例:
'a"b', 'a\'b'