メインコンテンツまでスキップ

JSON フィールドの概要

製品カタログ、コンテンツ管理システム、ユーザー設定エンジンなどのアプリケーションを構築する場合、ベクトル埋め込みとともに柔軟なメタデータを格納する必要がよくあります。製品属性はカテゴリによって異なり、ユーザー設定は時間の経過とともに変化し、ドキュメントのプロパティは複雑なネスト構造を持ちます。Zilliz Cloud の JSON フィールドは、パフォーマンスを犠牲にすることなく柔軟な構造化データを格納およびクエリできるようにすることで、この課題を解決します。

JSON フィールドとは?​

JSON フィールドは、Zilliz Cloud におけるスキーマ定義のデータ型(DataType.JSON)で、構造化されたキーと値のデータを格納します。従来の固定的なデータベースの列とは異なり、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 は 1つの JSON フィールドで、フラットな値(例:category、in_stock)、配列(tags)、ネストされたオブジェクト(supplier)が混在しています。

Notes

命名規則: JSON キーには英字、数字、アンダースコアのみを使用してください。特殊文字、スペース、ドットを使用するとクエリで解析の問題が発生する可能性があるため、避けてください。

JSON フィールドと動的フィールドの比較​

よく混同されるのが、JSON フィールドと動的フィールドの違いです。どちらも JSON に関係していますが、目的は異なります。

以下の表は、JSON フィールドと動的フィールドの主な違いをまとめたものです:

項目JSON フィールド動的フィールド
スキーマ定義DataType.JSON 型を使用してコレクションスキーマで明示的に宣言する必要があるスカラーフィールドです。宣言されていないフィールドを自動的に格納する非表示の JSON フィールド(名前は $meta)です。
ユースケーススキーマが既知で一貫している構造化データを格納します。固定スキーマに適合しない、柔軟で変化する、または半構造化されたデータを格納します。
制御フィールド名と構造を制御できます。未定義のフィールドについてはシステムが管理します。
クエリフィールド名または JSON フィールド内の対象キーを使用してクエリします:metadata["key"]。動的フィールドのキーを直接使用してクエリします:"dynamic_key"、または $meta 経由でクエリします:$meta["dynamic_key"]

基本的な操作​

JSON フィールドを使用する基本的なワークフローは、スキーマで定義し、データを挿入し、特定のフィルター式を使用してデータをクエリするという流れになります。

JSON フィールドを定義する​

JSON フィールドを使用するには、コレクションの作成時にコレクションスキーマで明示的に定義します。次の例では、DataType.JSON 型の metadata フィールドを持つコレクションを作成する方法を示します:

python
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
)
Notes

この例では、コレクションスキーマで定義された JSON フィールドは、nullable=True で null 値を許可します。詳細については、Nullable & Default を参照してください。

データを挿入する​

コレクションを作成したら、指定した JSON フィールドに構造化された JSON オブジェクトを含むエンティティを挿入します。データは辞書のリストとしてフォーマットする必要があります。

python
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 フィールドでフィルタリング操作を実行する前に、以下を確認してください:

  • 各ベクトルフィールドにインデックスを作成していること。

  • コレクションがメモリにロードされていること。

サンプルコードを表示
python
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" であるエンティティをフィルタリングするには:

python
# 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" であるエンティティをフィルタリングするには:

python
# 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 固有の演算子によるフィルタリング​

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
# 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)

To find a product that has at least one of the "electronics", "new", or "clearance" values under the tags key:

python
# 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 Operators を参照してください。

次のステップ:JSON クエリを高速化する​

既定では、高速化されていない JSON フィールドに対するクエリはすべての行のフルスキャンを実行するため、大規模なデータセットでは遅くなる可能性があります。JSON クエリを高速化するために、Zilliz Cloud は高度なインデックス作成とストレージ最適化の機能を提供しています。

Warning

Milvus 3.0.0 以降、オブジェクト全体の JSON インデックス作成(json_cast_type="JSON"、JSON フラットインデックスとも呼ばれます)は非推奨です。既存のインデックスと新規のインデックス作成リクエストは互換性のために引き続きサポートされますが、このモードは新しいワークロードには推奨されません。既知のクエリパスには JSON パスインデックスを使用するか、複雑または変化するドキュメント全体のクエリを高速化するには JSON Shredding の使用を検討してください。

以下の表は、それぞれの違いと最適なユースケースをまとめたものです:

手法最適な用途配列の高速化備考
JSON インデックス頻繁にアクセスされる少数のキー、特定の配列キーの配列はい(インデックス付き配列キーに対して)キーを事前に選択する必要があり、スキーマが変化した場合はメンテナンスが必要
JSON Shredding多数のキーにわたる全般的な高速化、多様なクエリに柔軟に対応はい(ブルートフォースクエリと比較して配列値をわずかに高速化)追加のストレージ設定が必要で、配列には依然としてキーごとのインデックスが必要
NGRAM インデックスワイルドカード検索、テキストフィールド内の部分文字列一致N/Anumeric/range フィルターには使用できません

ヒント: これらのアプローチは組み合わせることができます。たとえば、広範なクエリの高速化には JSON Shredding、高頻度の配列キーには JSON インデックス、柔軟なテキスト検索には NGRAM インデックスを使用します。

実装の詳細については、以下を参照してください:

FAQ​

JSON フィールドのサイズに制限はありますか?​

はい。各 JSON フィールドは 65,536 バイトに制限されています。

JSON フィールドは既定値の設定をサポートしていますか?​

いいえ、JSON フィールドは既定値をサポートしていません。ただし、フィールドを定義するときに nullable=True を設定すると、空のエントリを許可できます。

詳細については、Nullable & Default を参照してください。

JSON フィールドのキーの命名規則はありますか?​

はい。クエリとインデックス作成との互換性を確保するために、以下に従ってください:

  • JSON キーには英字、数字、アンダースコアのみを使用します。

  • 特殊文字、スペース、ドット(.、/ など)の使用は避けます。

  • 互換性のないキーは、フィルター式で解析の問題を引き起こす可能性があります。

Zilliz Cloud は JSON フィールドの文字列値をどのように処理しますか?​

Zilliz Cloud は、文字列値を JSON 入力に表示されるとおりに格納し、意味的な変換は行いません。引用符が正しくない文字列は、解析時にエラーになる可能性があります。

有効な文字列の例:

plaintext
"a\"b", "a'b", "a\\b"

無効な文字列の例:

plaintext
'a"b', 'a\'b'