JSONフィールドの概要
製品カタログ、コンテンツ管理システム、ユーザープレファレンスエンジンなどのアプリケーションを構築する際、ベクターエンベディングとともに柔軟なメタデータを保存する必要がよくあります。製品属性はカテゴリによって異なり、ユーザープレファレンスは時間とともに変化し、ドキュメントプロパティは複雑なネストされた構造を持っています。Zilliz CloudのJSONフィールドは、パフォーマンスを犠牲にすることなく柔軟な構造化データを保存およびクエリできる機能により、この課題を解決します。
JSONフィールドとは
JSONフィールドは、Zilliz Cloudにおけるスキーマ定義されたデータ型(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 はフラットな値(例:category、in_stock)、配列(tags)、およびネストされたオブジェクト(supplier)を含む単一のJSONフィールドです。
命名規則:JSONキーには英数字とアンダースコアのみを使用してください。クエリで解析の問題を引き起こす可能性があるため、特殊文字、スペース、またはドットは避けてください。
JSONフィールドと動的フィールドの違い
よくある混乱点は、JSONフィールドと動的フィールドとの違いです。両方ともJSONに関係していますが、異なる目的を果たします。
JSONフィールドと動的フィールドの主な違いを以下の表にまとめています:
機能 | JSONフィールド | 動的フィールド |
|---|---|---|
スキーマ定義 |
| 宣言されていないフィールドを自動的に保存する非表示のJSONフィールド(名前は |
使用例 | スキーマが既知で一貫している構造化データを保存。 | 固定スキーマに適合しない柔軟な、進化する、または準構造化されたデータを保存。 |
制御 | フィールド名と構造を制御できます。 | 未定義フィールド用にシステム管理。 |
クエリ | フィールド名またはJSONフィールド内の特定のキーを使用してクエリ: | 動的フィールドキーを直接使用してクエリ: |
基本操作
JSONフィールドを使用するための基本的なワークフローには、スキーマ内での定義、データの挿入、および特定のフィルター式を使用したデータのクエリが含まれます。
JSONフィールドを定義する
JSONフィールドを使用するには、コレクションを作成する際にスキーマ内で明示的に定義します。以下の例では、DataType.JSON型のmetadataフィールドを持つコレクションを作成する方法を示しています:
from pymilvus import MilvusClient, DataType
CLUSTER_ENDPOINT = "YOUR_CLUSTER_ENDPOINT"
TOKEN = "YOUR_CLUSTER_TOKEN"
# Milvusクライアントのセットアップ
client = MilvusClient(
uri=CLUSTER_ENDPOINT,
token=TOKEN
)
# スキーマの作成
schema = client.create_schema(auto_id=False, enable_dynamic_field=True)
schema.add_field(field_name="product_id", datatype=DataType.INT64, is_primary=True) # プライマリフィールド
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5) # ベクトルフィールド
# null値を許可するJSONフィールドを定義
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フィールド
"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"であるエンティティをフィルタリングするには:
# フィルター式を定義
filter = 'metadata["category"] == "electronics"'
client.search(
collection_name="product_catalog", # コレクション名
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # クエリベクトル(コレクションのベクターディムと一致する必要があります)
limit=5, # 返される結果の最大数
filter=filter, # フィルター式
output_fields=["product_id", "metadata"] # 検索結果に含めるフィールド
)
ネストされたキーsupplier["country"]が"USA"であるエンティティをフィルタリングするには:
# フィルター式を定義
filter = 'metadata["supplier"]["country"] == "USA"'
res = client.search(
collection_name="product_catalog", # コレクション名
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # クエリベクトル(コレクションのベクターディムと一致する必要があります)
limit=5, # 返される結果の最大数
filter=filter, # フィルター式
output_fields=["product_id", "metadata"] # 検索結果に含めるフィールド
)
print(res)
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"値を持つ製品を検索するには:
# フィルター式を定義
filter = 'json_contains(metadata["tags"], "summer_sale")'
res = client.search(
collection_name="product_catalog", # コレクション名
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # クエリベクトル(コレクションのベクターディムと一致する必要があります)
limit=5, # 返される結果の最大数
filter=filter, # フィルター式
output_fields=["product_id", "metadata"] # 検索結果に含めるフィールド
)
print(res)
tagsキー配下に"electronics"、"new"、または"clearance"値の少なくとも1つを持つ製品を検索するには:
# フィルター式を定義
filter = 'json_contains_any(metadata["tags"], ["electronics", "new", "clearance"])'
res = client.search(
collection_name="product_catalog", # コレクション名
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # クエリベクトル(コレクションのベクターディムと一致する必要があります)
limit=5, # 返される結果の最大数
filter=filter, # フィルター式
output_fields=["product_id", "metadata"] # 検索結果に含めるフィールド
)
print(res)
JSON固有の演算子の詳細については、JSON演算子を参照してください。
次:JSONクエリの高速化
デフォルトでは、高速化されていないJSONフィールドのクエリはすべての行をフルスキャンするため、大規模なデータセットでは遅くなる可能性があります。JSONクエリを高速化するために、Zilliz Cloudは高度なインデックスおよびストレージ最適化機能を提供します。
以下の表は、それらの違いと最適使用例をまとめています:
技術 | 最適対象 | 配列の高速化 | 注意 |
|---|---|---|---|
JSONインデックス | 頻繁にアクセスされるキーの小規模セット、特定の配列キーの配列 | はい(インデックス付き配列キー) | キーを事前選択する必要あり、スキーマが変更された場合はメンテナンスが必要 |
JSONシャレディング | 多くのキーにわたる一般的な高速化、多様なクエリに柔軟性 | はい(ブルートフォースクエリと比較して配列値をわずかに高速化) | 追加ストレージ設定、配列は引き続きキーベースインデックスが必要 |
NGRAMインデックス | ワイルドカード検索、テキストフィールドでの部分文字列一致 | 該当なし | 数値/範囲フィルターには不向き |
ヒント: これらのアプローチを組み合わせることができます。たとえば、幅広いクエリ高速化にはJSONシャレディングを使用し、高頻度の配列キーにはJSONインデックスを使用し、柔軟なテキスト検索にはNGRAMインデックスを使用するなどです。
実装の詳細については、以下を参照してください:
FAQ
JSONフィールドのサイズに制限はありますか?
はい。各JSONフィールドは65,536バイトに制限されています。
JSONフィールドはデフォルト値の設定をサポートしていますか?
いいえ、JSONフィールドはデフォルト値をサポートしていません。ただし、フィールド定義時にnullable=Trueを設定して空のエントリを許可できます。
詳細についてはNullable & Defaultを参照してください。
JSONフィールドキーには命名規則がありますか?
はい、クエリおよびインデックスとの互換性を確保するために:
- JSONキーには英数字とアンダースコアのみを使用してください。
- 特殊文字、スペース、またはドット(
.,/など)の使用は避けてください。 - 互換性のないキーはフィルター式で解析の問題を引き起こす可能性があります。
Zilliz CloudはJSONフィールド内の文字列値をどのように処理しますか?
Zilliz CloudはJSON入力でのように文字列値を正確に保存します—意味的な変換は行いません。不適切にクォートされた文字列は解析中にエラーになる可能性があります。
有効な文字列の例:
"a\"b", "a'b", "a\\b"
無効な文字列の例:
'a"b', 'a\'b'