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

JSON インデックス

JSON フィールドは、Zilliz Cloud で構造化メタデータを柔軟に保存する方法を提供します。インデックスがない場合、JSON フィールドに対するクエリはコレクション全体のスキャンが必要になり、データセットの増加に伴って遅くなります。JSON インデックス作成では、JSON データ内の特定のパスにインデックスを作成するため、そのパスに対する等価、範囲、その他のフィルタークエリを高速に実行できます。

JSON インデックス作成は次のような場合に最適です:

  • 一貫した既知のキーを持つ構造化スキーマ

  • 特定の JSON パスに対する等価、IN、範囲、テキスト一致クエリ

  • どのキーをインデックス化するかを正確に制御する必要があるシナリオ

複雑な JSON ドキュメントで多様なクエリパターンを使用する場合は、代替として JSON Shredding を検討してください。

インデックスタイプの概要​

Zilliz Cloud は、JSON パス用に 4 つのインデックスタイプを提供しています。それぞれ異なるクエリパターンに適しています。

インデックスタイプを選択する前に、JSON パスのキャスト型を特定してください。キャスト型は、Zilliz Cloud がそのパスの値をどのように解釈するか、およびどのインデックスタイプを使用できるかを決定します。

キャスト型を理解する​

json_cast_type は、json_path の値を解釈し、インデックスを作成するために使用するデータ型です。フィールドスキーマ型とは異なります。フィールドは引き続き JSON フィールドですが、インデックス化された各パスは、特定のスカラー、配列、または JSON オブジェクト型として扱われます。

パスに保存されている値に一致するキャスト型を選択してください。キャスト型が特定のインデックスタイプで動作するかどうかを確認するには、互換性リファレンス を参照してください。

キャスト型パス値が次の場合に使用します...値の例
BOOLブール値true
DOUBLE数値99.99
VARCHAR文字列値"electronics"
ARRAY_BOOLブール値の配列[true, false]
ARRAY_DOUBLE数値の配列[1.2, 3.14]
ARRAY_VARCHAR文字列値の配列["tag1", "tag2"]
JSONJSON オブジェクト全体またはサブオブジェクト。オブジェクト全体の JSON インデックス作成は Milvus 3.0.0 以降非推奨です。{"supplier": {"country": "USA"}}

同じパスの値に一貫性のない型がある場合、キャスト型に一致する値のみがインデックス化されます。たとえば、metadata["price"] に 99.99 と "99.99" の両方が含まれている場合、DOUBLE キャスト型のインデックスには数値が含まれ、文字列値はスキップされます。インデックス作成中に文字列値を変換するには json_cast_function を使用します。詳細は、例 5: インデックス作成時にデータ型を変換する を参照してください。

インデックスタイプを選択する​

キャスト型を選択したら、クエリパターンに応じてインデックスタイプを選択します。

クエリパターン推奨インデックスタイプキャスト型の要件注記
スカラー値に対する等価フィルターと範囲フィルターの混在AUTOINDEXBOOL、DOUBLE、または VARCHAR を使用します。値のカーディナリティに基づいて、Zilliz Cloud が内部インデックスレイアウトを選択できるようにします。
JSON 配列内の値に対するフィルターINVERTEDARRAY_BOOL、ARRAY_DOUBLE、または ARRAY_VARCHAR を使用します。すべての配列キャスト型で必要です。
オブジェクト全体またはサブオブジェクトのインデックス作成(非推奨)INVERTED または AUTOINDEX(互換性のみ)JSON を使用します。互換性のためにサポートされています。新しいワークロードでは、パス固有のインデックスを作成するか、JSON Shredding を検討してください。
数値またはソート可能な文字列に対する範囲フィルターSTL_SORT または AUTOINDEXDOUBLE または VARCHAR を使用します。ソートされたレイアウトを強制するには STL_SORT を使用し、自動選択が必要な場合は AUTOINDEX を使用します。
低カーディナリティ値に対する等価フィルターまたは IN フィルターBITMAP または AUTOINDEXBOOL または VARCHAR を使用します。ビットマップレイアウトを強制するには BITMAP を使用します。数値の場合は、AUTOINDEX または STL_SORT を使用します。

迷った場合は、スカラーパスの AUTOINDEX から開始してください。配列キャスト型とテキスト一致クエリには INVERTED を明示的に使用します。INVERTED または AUTOINDEX を使用するオブジェクト全体の JSON インデックス作成は引き続きサポートされますが、Milvus 3.0.0 以降は非推奨です。

AUTOINDEX​

AUTOINDEX の動作は、指定した json_cast_type によって異なります。Milvus 3.0 では、JSON パスインデックスに対して AUTOINDEX が常に INVERTED に解決されるわけではありません。

キャスト型AUTOINDEX の動作
BOOL、DOUBLE、VARCHAR値のカーディナリティに基づいて BITMAP と STL_SORT のどちらかを選択します。
ARRAY_BOOL、ARRAY_DOUBLE、ARRAY_VARCHARサポートされていません。インデックスタイプとして INVERTED を明示的に使用してください。
JSONオブジェクト全体またはサブオブジェクトのインデックス作成に INVERTED を使用します。このモードは Milvus 3.0.0 以降非推奨です。

スカラーキャスト型(BOOL、DOUBLE、VARCHAR)では、Zilliz Cloud に内部インデックスレイアウトを選択させる場合、AUTOINDEX を最初に使用することを推奨します。インデックス構築中に、Zilliz Cloud は JSON パスの値のカーディナリティを測定します。カーディナリティとは、そのパスにある個別の値の数です。

カーディナリティに基づいて、Zilliz Cloud は 2 つの内部レイアウトのいずれかを選択します:

  • 低カーディナリティ: 値が頻繁に繰り返される場合です。たとえば、true と false を持つ metadata["in_stock"]、または少数のステータス文字列を持つ metadata["status"] です。Zilliz Cloud は、等価フィルターと IN フィルターを高速化するために、内部的に BITMAP インデックスを構築します。

  • 高カーディナリティ: ほとんどの値が個別である場合です。たとえば、metadata["price"]、metadata["created_at"]、または metadata["product_id"] です。Zilliz Cloud は、>、<、>=、<= などの範囲フィルターを高速化するために、内部的に STL_SORT インデックスを構築します。

デフォルトの BITMAP と STL_SORT のしきい値は 100 個の個別値です。このしきい値は bitmap_cardinality_limit で調整できます。詳細は、AUTOINDEX の BITMAP と STL_SORT のしきい値を調整するにはどうすればよいですか? を参照してください。

📘Notes

Milvus 3.0 での動作変更。以前のバージョンでは、JSON パスに対する AUTOINDEX は常に INVERTED インデックスを構築していました。Milvus 3.0 以降、AUTOINDEX はスカラーキャスト型に対して BITMAP と STL_SORT のいずれかを選択します。JSON の場合、オブジェクト全体の JSON インデックス作成は非推奨ですが、AUTOINDEX は引き続き INVERTED を使用します。配列キャスト型とテキスト一致クエリの場合は、INVERTED を明示的に指定してください。

INVERTED​

INVERTED は、テキスト一致クエリや配列のインデックス作成が必要な場合に最適です。非推奨のオブジェクト全体の JSON インデックス作成でも引き続き使用できます。

次の場合は INVERTED を明示的に指定してください:

  • JSON 配列内の値をインデックス化する必要がある場合。

  • JSON オブジェクト全体またはサブオブジェクトの既存インデックスを維持し、INVERTED の動作を明示したい場合。

  • 等価、IN、範囲、テキスト一致、および配列クエリを処理する 1 つのインデックスタイプが必要な場合。オブジェクト全体のサポートは互換性のために引き続き利用できますが、インデックスサイズが大きくなります。

JSON オブジェクト全体の既存インデックス(json_cast_type="JSON")では、引き続き INVERTED または AUTOINDEX のいずれかを使用できます。AUTOINDEX はこのキャスト型に INVERTED を使用します。オブジェクト全体の JSON インデックス作成は、新しいワークロードには推奨されません。

詳細は、INVERTED を参照してください。

STL_SORT​

STL_SORT は、JSON パスの値をソート順で保存します。数値またはソート可能な文字列値に対する範囲フィルターに最適化されています。

STL_SORT は DOUBLE および VARCHAR キャスト型のみをサポートします。次の場合に使用します:

  • フィルターで >、<、>=、または <= を使用して値を比較する場合。

  • インデックス化された値のカーディナリティが高い場合。たとえば、価格、タイムスタンプ、ID、またはソート可能なコードです。

  • AUTOINDEX に選択させるのではなく、ソートされたレイアウトを強制する場合。

STL_SORT は BOOL、ARRAY_*、または JSON キャスト型をサポートしていません。配列には INVERTED を使用してください。既存のオブジェクト全体インデックスは引き続き INVERTED または AUTOINDEX を使用できますが、オブジェクト全体の JSON インデックス作成は非推奨です。

詳細は、STL_SORT を参照してください。

BITMAP​

BITMAP は、JSON パスの個別の値ごとにコンパクトなビットマップを作成します。頻繁に繰り返される値に対する等価フィルターと IN フィルターに最適化されています。

BITMAP は BOOL および VARCHAR キャスト型のみをサポートします。次の場合に使用します:

  • フィルターで == または IN を使用する場合。

  • インデックス化された値のカーディナリティが低い場合。たとえば、ブール値、ステータス値、または少数のカテゴリです。

  • AUTOINDEX に選択させるのではなく、ビットマップレイアウトを強制する場合。

BITMAP は DOUBLE、ARRAY_*、または JSON キャスト型をサポートしていません。数値の場合は、代わりに AUTOINDEX、STL_SORT、または INVERTED を使用してください。

詳細は、BITMAP を参照してください。

互換性リファレンス​

サポートされている (cast type, index type) の組み合わせをすばやく確認するには、次のマトリックスを使用してください。

キャスト型説明値の例AUTOINDEXINVERTEDSTL_SORTBITMAP
BOOLブール値(true/false)。trueはいはいいいえはい
DOUBLE数値(整数または浮動小数点数)。99.99はいはいはいいいえ
VARCHAR文字列値。"electronics"はいはいはいはい
ARRAY_BOOLブール値の配列。[true, false]いいえはいいいえいいえ
ARRAY_DOUBLE数値の配列。[1.2, 3.14]いいえはいいいえいいえ
ARRAY_VARCHAR文字列の配列。["tag1", "tag2"]いいえはいいいえいいえ
JSON自動型推論とフラット化を伴う JSON オブジェクト全体またはサブオブジェクト。Milvus 3.0.0 以降非推奨です。任意のネストされたオブジェクトはい(非推奨)はい(非推奨)いいえいいえ

No と表示されたセルでは、Zilliz Cloud はインデックス作成時にリクエストを拒否します。配列キャスト型の場合は、INVERTED を明示的に使用してください(AUTOINDEX は配列をサポートしていません)。

JSON インデックスを作成する​

このセクションでは、さまざまな形状の JSON データのインデックス作成について説明します。すべての例では、以下のサンプル構造を使用し、metadata という名前の 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"
}
}
}
}

基本的な設定​

以下の例では、Zilliz Cloud デプロイに接続された client という名前の MilvusClient と、metadata という名前の JSON フィールドをすでに含むコレクションがあることを前提としています。これらを最初から設定する必要がある場合は、以下のブロックを展開してください。

接続してサンプルコレクションを作成する
python
from pymilvus import DataType, MilvusClient

client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT", token="YOUR_CLUSTER_TOKEN")

# Define a schema with a JSON field
schema = client.create_schema(enable_dynamic_field=False)
schema.add_field("pk", DataType.INT64, is_primary=True, auto_id=False)
schema.add_field("vec", DataType.FLOAT_VECTOR, dim=4)
schema.add_field("metadata", DataType.JSON, nullable=True)

# Minimal vector index so the collection can be loaded
vec_index = client.prepare_index_params()
vec_index.add_index(field_name="vec", index_type="AUTOINDEX", metric_type="L2")

client.create_collection(
collection_name="your_collection_name",
schema=schema,
index_params=vec_index,
)

# Insert one row that matches the sample JSON structure above
client.insert(
collection_name="your_collection_name",
data=[{
"pk": 1,
"vec": [0.1, 0.2, 0.3, 0.4],
"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"
}
}
}
}],
)

以下の例で追加するインデックス定義を収集するための index-params オブジェクトを準備します:

python
index_params = client.prepare_index_params()

後続の各例では、1 回の index_params.add_index(...) 呼び出しを示します。データに一致するものを選択し、同じ index_params オブジェクトに対して呼び出してください。最後に、すべてを 1 回の client.create_index(...) 呼び出しで適用します。詳細は、インデックスを適用する を参照してください。

例 1: AUTOINDEX でトップレベルのキーをインデックス化する​

製品カテゴリによる高速なフィルタリングのために、category フィールドをインデックス化します。AUTOINDEX を使用すると、Zilliz Cloud はデータ内に存在する個別カテゴリの数に基づいて BITMAP または STL_SORT を選択します。

python
index_params.add_index(
field_name="metadata",
index_type="AUTOINDEX",
index_name="category_index",
params={
"json_path": 'metadata["category"]',
"json_cast_type": "VARCHAR",
}
)

例 2: ネストされたキーをインデックス化する​

サプライヤーの連絡先を検索するために、深くネストされた email フィールドをインデックス化します。json_path パラメーターは、任意の深さのブラケット表記を受け入れます。

python
index_params.add_index(
field_name="metadata",
index_type="AUTOINDEX",
index_name="email_index",
params={
"json_path": 'metadata["supplier"]["contact"]["email"]',
"json_cast_type": "VARCHAR",
}
)

例 3: STL_SORT を使用した範囲クエリ​

パスに対するクエリが主に範囲比較(>、<、>=、<=)になるとわかっている場合は、STL_SORT を直接選択してください。これにより、カーディナリティの測定を省略し、ソートされたレイアウトをすぐに構築できます。

python
index_params.add_index(
field_name="metadata",
index_type="STL_SORT",
index_name="price_index",
params={
"json_path": 'metadata["price"]',
"json_cast_type": "DOUBLE",
}
)

インデックス作成後、metadata["price"] > 50 AND metadata["price"] < 100 のような範囲クエリは、フルスキャンではなくバイナリ検索を使用します。

例 4: BITMAP を使用した等価クエリ​

ステータスコード、ブール値、列挙型のような文字列などの低カーディナリティキーには、BITMAP を直接選択してください。等価クエリと IN クエリはビットマップ操作になります。

python
index_params.add_index(
field_name="metadata",
index_type="BITMAP",
index_name="in_stock_index",
params={
"json_path": 'metadata["in_stock"]',
"json_cast_type": "BOOL",
}
)

BITMAP は、少数の個別文字列値を持つ status 列のようなフィールドにも非常によく適しています。

例 5: インデックス作成時にデータ型を変換する​

数値データが誤って文字列として保存されている場合は、STRING_TO_DOUBLE を使用して、インデックス構築中に値を数値へ変換します。

python
index_params.add_index(
field_name="metadata",
index_type="AUTOINDEX",
index_name="string_to_double_index",
params={
"json_path": 'metadata["string_price"]',
"json_cast_type": "DOUBLE",
"json_cast_function": "STRING_TO_DOUBLE",
}
)

行の変換が失敗した場合(たとえば、"invalid" のような非数値文字列)、その行はインデックス作成中にスキップされます。

例 6: JSON オブジェクト全体をインデックス化する​

🚧Warning

Milvus 3.0.0 以降、JSON フラットインデックスとも呼ばれるオブジェクト全体の JSON インデックス作成(json_cast_type="JSON")は非推奨です。既存のインデックスと新しいインデックス作成リクエストは互換性のために引き続きサポートされますが、このモードは新しいワークロードには推奨されません。既知のクエリパスには JSON パスインデックスを作成してください。広範なクエリパターンを持つ複雑または進化する JSON ドキュメントの場合は、JSON Shredding を検討してください。JSON シャーディングは配列内の値を高速化しません。そのようなクエリには、配列キャスト型を指定した JSON パスインデックスを使用してください。

互換性のある既存のワークロードでは、json_cast_type="JSON" を設定すると、指定されたパスの完全な構造がインデックス化されます。Zilliz Cloud はネストされたオブジェクトをパスにフラット化し、各値の型を自動的に推論します。パス以下のすべてのキーが検索可能になります。

フラット化と型推論は転置インデックスの機能であるため、AUTOINDEX は JSON キャスト型に対して透過的に INVERTED を使用します。

metadata オブジェクト全体をインデックス化します:

python
index_params.add_index(
field_name="metadata",
index_type="AUTOINDEX",
index_name="metadata_full_index",
params={
"json_path": "metadata",
"json_cast_type": "JSON",
}
)

または、すべての supplier 情報など、サブオブジェクトをインデックス化します:

python
index_params.add_index(
field_name="metadata",
index_type="AUTOINDEX",
index_name="supplier_index",
params={
"json_path": 'metadata["supplier"]',
"json_cast_type": "JSON",
}
)

オブジェクト全体をインデックス化すると、インデックスサイズが増加します。深くネストされたドキュメントと多様なクエリパターンを使用する新しいワークロードでは、パス固有のインデックスを使用するか、JSON Shredding を検討してください。

インデックスを適用する​

すべてのインデックスパラメーターを追加したら、それらをコレクションに適用します:

python
client.create_index(
collection_name="your_collection_name",
index_params=index_params
)

インデックスの構築は非同期で実行されます。特定のインデックスの構築状態を確認するには、client.describe_index(...) を使用します。構築が完了すると state フィールドに Finished が表示され、total_rows、indexed_rows、および pending_index_rows に進行状況が表示されます。

python
client.describe_index(
collection_name="your_collection_name",
index_name="category_index",
)

応答例:

json
{
"json_path": "metadata[\"category\"]",
"json_cast_type": "VARCHAR",
"index_type": "AUTOINDEX",
"field_name": "metadata",
"index_name": "category_index",
"total_rows": 20,
"indexed_rows": 20,
"pending_index_rows": 0,
"state": "Finished"
}

state が Finished を報告すると、インデックス化されたパスに対するクエリは自動的に新しいインデックスを使用します。

AUTOINDEX エントリの場合、この応答の index_type フィールドは AUTOINDEX として報告されます。Zilliz Cloud は、構築時に選択された基盤レイアウト(BITMAP または STL_SORT)を公開しません。この選択は内部最適化として扱ってください。選択されたレイアウトに関係なく、パスに対する等価、IN、および範囲クエリは機能します。

FAQ​

AUTOINDEX と明示的なインデックスタイプのどちらを選択するにはどうすればよいですか?​

AUTOINDEX から開始してください。データのカーディナリティから適切なレイアウトを選択し、JSON パスに対するほとんどの等価、IN、および範囲クエリをカバーします。次の場合は明示的なタイプを選択してください:

  • クエリパターンがわかっている場合(たとえば、常に範囲クエリには STL_SORT を使用し、常に低カーディナリティ値に対する等価クエリには BITMAP を使用する)で、カーディナリティの測定を省略したい場合。

  • テキスト一致クエリまたは部分文字列クエリが必要な場合。INVERTED を使用してください。

  • 配列キャスト型をインデックス化する場合。INVERTED を明示的に使用してください。

  • 既存のオブジェクト全体の JSON インデックスを維持する場合。INVERTED と AUTOINDEX はどちらも互換性のために引き続きサポートされますが、オブジェクト全体の JSON インデックス作成は Milvus 3.0.0 以降非推奨です。

クエリのフィルター式が、インデックス化されたキャスト型とは異なる型を使用した場合はどうなりますか?​

フィルター式がインデックスの json_cast_type とは異なる型を使用している場合、Zilliz Cloud はインデックスを使用せず、データが許せば低速なブルートフォーススキャンにフォールバックする可能性があります。最高のパフォーマンスを得るには、フィルター式を常にインデックスのキャスト型に合わせてください。たとえば、数値インデックスが json_cast_type="DOUBLE" で作成されている場合、数値のフィルター条件のみがインデックスを利用します。

JSON キーのデータ型がエンティティごとに一貫していない場合はどうなりますか?​

型の不一致は部分的なインデックス作成につながる可能性があります。たとえば、metadata["price"] が数値(99.99)と文字列("99.99")の両方として保存されており、json_cast_type="DOUBLE" でインデックスを作成すると、数値のみがインデックス化されます。文字列形式のエントリはスキップされ、フィルター結果に表示されません。インデックス作成時に文字列を数値へ強制変換するには json_cast_function="STRING_TO_DOUBLE" を使用するか、すべてのエントリが 1 つの型を共有するようにソースデータを修正してください。

同じ JSON キーに複数のインデックスを作成できますか?​

いいえ。Zilliz Cloud では、キャスト型やインデックスタイプに関係なく、(field, json_path) のペアごとに最大 1 つのインデックスを使用できます。同じパスに INVERTED と BITMAP の両方のインデックスを作成したり、異なるキャスト型で同じパスに 2 つのインデックスを作成したりすることはできません。ただし、JSON オブジェクト全体のインデックスと、そのオブジェクト内のネストされたキーの個別インデックスは、異なるパスであるため作成できます。

AUTOINDEX の BITMAP と STL_SORT のしきい値を調整するにはどうすればよいですか?​

デフォルトでは、インデックス化された値の個別値が 100 個以下の場合、AUTOINDEX は BITMAP を選択し、それ以外の場合は STL_SORT を選択します。インデックスパラメーターに "bitmap_cardinality_limit" を追加することで、このしきい値を上書きできます(範囲: 1-1000):

python
index_params.add_index(
field_name="metadata",
index_type="AUTOINDEX",
index_name="category_index",
params={
"json_path": 'metadata["category"]',
"json_cast_type": "VARCHAR",
"bitmap_cardinality_limit": 200, # use BITMAP up to 200 distinct values
}
)

ほとんどのユーザーはこの設定を調整する必要はありません。ビットマップ化を希望する中程度のカーディナリティのフィールドがある場合は値を上げてください。AUTOINDEX をより早く STL_SORT に誘導する場合は値を下げてください。INVERTED、STL_SORT、または BITMAP を明示的に指定した場合、この設定は無視されます。