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

Dynamic Field

Zilliz Cloud では、dynamic field と呼ばれる特別な機能により、柔軟で変化し続ける構造を持つエンティティを挿入できます。このフィールドは $meta という名前の非表示の JSON フィールドとして実装されており、collection schema で明示的に定義されていないデータ内のすべてのフィールドを自動的に保存します。

仕組み

dynamic field が有効になっている場合、Zilliz Cloud は各エンティティに非表示の $meta フィールドを追加します。このフィールドは JSON 型であるため、JSON と互換性のある任意のデータ構造を保存でき、JSON path 構文を使用して index を作成できます。

データ挿入時には、schema で宣言されていないフィールドはすべて、この dynamic field 内にキーと値のペアとして自動的に保存されます。

$meta を手動で管理する必要はありません。Zilliz Cloud が透過的に処理します。

たとえば、collection schema で idvector のみを定義し、次のエンティティを挿入したとします。

json
{
"id": 1,
"vector": [0.1, 0.2, 0.3],
"name": "Item A", // Not in schema
"category": "books" // Not in schema
}

dynamic field 機能を有効にすると、Zilliz Cloud は内部的に次のように保存します。

json
{
"id": 1,
"vector": [0.1, 0.2, 0.3],
"$meta": {
"name": "Item A",
"category": "books"
}
}

これにより、schema を変更することなくデータ構造を進化させることができます。

一般的なユースケースは次のとおりです。

  • オプションのフィールドや取得頻度の低いフィールドの保存

  • エンティティごとに異なるメタデータの保存

  • 特定の dynamic field キーに対する index による柔軟なフィルタリングのサポート

サポートされるデータ型

dynamic field は、単純な値と複雑な値の両方を含む、Zilliz Cloud が提供するすべての scalar データ型をサポートしています。これらのデータ型は、$meta に保存されるキーの値に適用されます。

サポートされる型は次のとおりです。

  • 文字列 (VARCHAR)

  • 整数 (INT8, INT32, INT64)

  • 浮動小数点数 (FLOAT, DOUBLE)

  • 真偽値 (BOOL)

  • scalar 値の配列 (ARRAY)

  • JSON オブジェクト (JSON)

例:

json
{
"brand": "Acme",
"price": 29.99,
"in_stock": true,
"tags": ["new", "hot"],
"specs": {
"weight": "1.2kg",
"dimensions": { "width": 10, "height": 20 }
}
}

上記の各キーと値はすべて $meta フィールド内に保存されます。

dynamic field を有効にする

dynamic field 機能を使用するには、collection schema の作成時に enable_dynamic_field=True を設定します。

python
from pymilvus import MilvusClient, DataType

# Initialize client
client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT")

# Create schema with dynamic field enabled
schema = client.create_schema(
auto_id=False,
enable_dynamic_field=True,
)

# Add explicitly defined fields
schema.add_field(field_name="my_id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="my_vector", datatype=DataType.FLOAT_VECTOR, dim=5)

# Create the collection
client.create_collection(
collection_name="my_collection",
schema=schema
)

collection にエンティティを挿入する

dynamic field を使用すると、スキーマで定義されていない追加フィールドを挿入できます。これらのフィールドは自動的に $meta に保存されます。

python
entities = [
{
"my_id": 1, # Explicitly defined primary field
"my_vector": [0.1, 0.2, 0.3, 0.4, 0.5], # Explicitly defined vector field
"overview": "Great product", # Scalar key not defined in schema
"words": 150, # Scalar key not defined in schema
"dynamic_json": { # JSON key not defined in schema
"varchar": "some text",
"nested": {
"value": 42.5
},
"string_price": "99.99" # Number stored as string
}
}
]

client.insert(collection_name="my_collection", data=entities)

dynamic field のキーにインデックスを作成する

Zilliz Cloud では、JSON path indexing を使用して dynamic field 内の特定のキーにインデックスを作成できます。これらは scalar 値でも、JSON オブジェクト内のネストされた値でも構いません。

📘注意

dynamic field キーへのインデックス作成は任意です。インデックスがなくても dynamic field キーで query や filter を実行できますが、総当たり検索になるためパフォーマンスが低下する可能性があります。

JSON path indexing の構文

JSON path index を作成するには、以下を指定します。

  • JSON path (json_path): インデックスを作成したい JSON オブジェクト内のキーまたはネストされたフィールドへのパス。

    • 例: metadata["category"]

      これは、インデックスエンジンが JSON 構造内のどこを参照するかを定義します。

  • JSON cast type (json_cast_type): Zilliz Cloud が指定されたパスの値を解釈し、インデックス化する際に使用するデータ型。

    • この型は、インデックス対象フィールドの実際のデータ型と一致している必要があります。

    • 完全な一覧については、Supported JSON cast types を参照してください。

JSON path を使用して dynamic field キーにインデックスを作成する

dynamic field は JSON field であるため、JSON path 構文を使ってその中の任意のキーにインデックスを作成できます。これは単純な scalar 値にも、複雑なネスト構造にも対応します。

JSON path の例:

  • 単純なキーの場合: overview, words

  • ネストされたキーの場合: dynamic_json['varchar'], dynamic_json['nested']['value']

python
index_params = client.prepare_index_params()

# Index a simple string key
index_params.add_index(
field_name="overview", # Key name in the dynamic field
index_type="AUTOINDEX", # Must be set to AUTOINDEX for JSON path indexing
index_name="overview_index", # Unique index name
params={
"json_cast_type": "varchar", # Data type that Zilliz Cloud uses when indexing the values
"json_path": "overview" # JSON path to the key
}
)

# Index a simple numeric key
index_params.add_index(
field_name="words", # Key name in the dynamic field
index_type="AUTOINDEX", # Must be set to AUTOINDEX for JSON path indexing
index_name="words_index", # Unique index name
params={
"json_cast_type": "double", # Data type that Zilliz Cloud uses when indexing the values
"json_path": "words" # JSON path to the key
}
)

# Index a nested key within a JSON object
index_params.add_index(
field_name="dynamic_json", # JSON key name in the dynamic field
index_type="AUTOINDEX", # Must be set to AUTOINDEX for JSON path indexing
index_name="json_varchar_index", # Unique index name
params={
"json_cast_type": "varchar", # Data type that Zilliz Cloud uses when indexing the values
"json_path": "dynamic_json['varchar']" # JSON path to the nested key
}
)

# Index a deeply nested key
index_params.add_index(
field_name="dynamic_json",
index_type="AUTOINDEX", # Must be set to AUTOINDEX for JSON path indexing
index_name="json_nested_index", # Unique index name
params={
"json_cast_type": "double",
"json_path": "dynamic_json['nested']['value']"
}
)

型変換に JSON cast 関数を使う

dynamic field キーに不正な形式の値が含まれている場合(例: 数値が文字列として保存されている場合)、cast 関数を使って変換できます。

python
# Convert a string to double before indexing
index_params.add_index(
field_name="dynamic_json", # JSON key name
index_type="AUTOINDEX",
index_name="json_string_price_index",
params={
"json_path": "dynamic_json['string_price']",
"json_cast_type": "double", # Must be the output type of the cast function
"json_cast_function": "STRING_TO_DOUBLE" # Case insensitive; convert string to double
}
)
📘注意
  • 型変換に失敗した場合(例: 値 "not_a_number" を数値に変換できない場合)、その値はスキップされ、インデックス化されません。

  • cast 関数のパラメータの詳細については、JSON Field Overview を参照してください。

collection にインデックスを適用する

インデックスパラメータを定義した後、create_index() を使ってそれらを collection に適用できます。

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

dynamic field キーで filter する

dynamic field キーを含むエンティティを挿入した後は、標準の filter expression を使ってそれらを filter できます。

  • 非 JSON キー(例: 文字列、数値、ブール値)の場合は、キー名を直接参照できます。

  • JSON オブジェクトを格納するキーの場合は、JSON path 構文を使ってネストされた値にアクセスします。

前のセクションの example entity に基づくと、有効な filter expression には以下が含まれます。

python
filter = 'overview == "Great product"' # Non-JSON key
filter = 'words >= 100' # Non-JSON key
filter = 'dynamic_json["nested"]["value"] < 50' # JSON object key

dynamic field キーの取得: 検索結果または query 結果で dynamic field キーを返すには、filter 時と同じ JSON path 構文を使って output_fields パラメータにそれらを明示的に指定する必要があります。

python
# Example: Include dynamic field keys in search results
results = client.search(
collection_name="my_collection",
data=[[0.1, 0.2, 0.3, 0.4, 0.5]],
filter=filter, # Filter expression defined earlier
limit=10,
output_fields=[
"overview", # Simple dynamic field key
"dynamic_json" # Nested JSON key
]
)
📘注意

dynamic field キーはデフォルトでは結果に含まれず、明示的に要求する必要があります。

サポートされている演算子と filter expression の完全な一覧については、Filtered Search を参照してください。

まとめると

ここまでで、dynamic field を使ってスキーマで定義されていないキーを柔軟に保存し、インデックス化する方法を学びました。dynamic field キーが一度挿入されると、特別な構文を必要とせず、filter expression 内で他の field と同じように使用できます。

実際のアプリケーションでワークフローを完結させるには、さらに以下も必要です。

  • vector field にインデックスを作成する(各 collection で必須)

    AUTOINDEX Explained とその関連ページを参照してください

  • collection を load する

    Load & Release を参照してください

  • JSON path filter を使って search または query する

    Filtered SearchJSON Operators を参照してください

FAQ

dynamic field キーを使う代わりに、いつ field をスキーマで明示的に定義すべきですか?

次のような場合は、dynamic field キーを使うのではなく、field をスキーマで明示的に定義するべきです。

  • その field が output_fields に頻繁に含まれる場合: output_fields を通じて効率的に取得できることが保証されるのは、明示的に定義された field のみです。dynamic field キーは高頻度の取得向けに最適化されておらず、パフォーマンスオーバーヘッドが発生する可能性があります。

  • その field へのアクセスや filter が頻繁な場合: dynamic field キーにインデックスを作成すれば、固定スキーマ field と同等の filter パフォーマンスを得られることがありますが、明示的に定義された field の方が構造が明確で保守性にも優れます。

  • field の挙動を完全に制御したい場合: 明示的 field は、スキーマレベルの制約、バリデーション、より明確な型付けをサポートしており、データ整合性や一貫性の管理に役立ちます。

  • インデックスの不整合を避けたい場合: dynamic field キー内のデータは、型や構造の不一致が発生しやすくなります。固定スキーマを使用することで、特にインデックスや cast を使用する予定がある場合に、データ品質を確保しやすくなります。

既存の collection にある dynamic field キーを明示的な scalar field にしたい場合は、Alter Collection Schema を参照してください。既存 collection レベルの dynamic field 設定は collection properties を通じて管理されます。詳細は Modify Collection を参照してください。

同じ dynamic field キーに対して、異なるデータ型で複数のインデックスを作成できますか?

いいえ、JSON path ごとに作成できるインデックスは 1 つだけです。dynamic field キーに混在した型の値(例: 一部は文字列、一部は数値)が含まれていても、そのパスをインデックス化する際には単一の json_cast_type を選択する必要があります。現時点では、同じキーに対して異なる型で複数のインデックスを作成することはサポートされていません。

dynamic field キーにインデックスを作成するとき、データの cast に失敗したらどうなりますか?

dynamic field キーにインデックスを作成していて、データの cast に失敗した場合—たとえば double に cast するはずの値が "abc" のような数値でない文字列だった場合—その特定の値はインデックス作成時に黙ってスキップされます。その値はインデックスに含まれないため、インデックスに依存するfilter ベースの search や query 結果には返されません

これにはいくつか重要な意味があります。

  • フルスキャンへのフォールバックはない: エンティティの大半が正常にインデックス化されている場合、filter query は完全にインデックスに依存します。cast に失敗したエンティティは、論理的には filter 条件に一致していても、結果セットから除外されます。

  • 検索精度のリスク: 大規模データセットでデータ品質にばらつきがある場合(特に dynamic field キー内)、この挙動により想定外の結果欠落が起こる可能性があります。インデックスを作成する前に、一貫した有効なデータ形式を確保することが重要です。

  • cast 関数は慎重に使用する: インデックス作成中に json_cast_function を使って文字列を数値に変換する場合、その文字列値が確実に変換可能であることを確認してください。json_cast_type と実際の変換後の型が一致しない場合、エラーやエントリのスキップが発生します。

query で、インデックス化された cast type とは異なるデータ型を使うとどうなりますか?

query が、インデックス作成時に使用された型とは異なるデータ型で dynamic field キーを比較する場合(例: インデックスが double に cast されているのに、query では文字列比較を行う場合)、システムはそのインデックスを使用しません。また、可能な場合に限りフルスキャンにフォールバックすることがあります。最適なパフォーマンスと精度のために、query で使用する型がインデックス作成時の json_cast_type と一致するようにしてください。

Ctrl I