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

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 は、フラットな値(例: category、in_stock)、配列(tags)、ネストされたオブジェクト(supplier)を組み合わせて含む単一の JSON フィールドです。

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 とデフォルト値 を参照してください。

データを挿入する​

コレクションを作成したら、指定した 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)

tags キーの下に "electronics"、"new"、"clearance" のいずれかの値を持つ商品を検索するには、次のようにします:

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 演算子 を参照してください。

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

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

Warning

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

以下の表に、各手法の違いと最適な使用シナリオをまとめます。

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

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

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

FAQ​

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

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

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

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

詳細については、Nullable とデフォルト値 を参照してください。

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

はい。クエリおよびインデックス作成との互換性を確保するには、次の点に従ってください:

  • JSON キーには英字、数字、アンダースコアのみを使用してください。

  • 特殊文字、スペース、ドット(.、/ など)は使用しないでください。

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

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

Zilliz Cloud は、文字列値を JSON 入力に含まれるとおりに、意味的な変換を行わずに保存します。引用符の付け方が不適切な文字列は、解析時にエラーになる可能性があります。

有効な文字列の例:

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

無効な文字列の例:

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