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

Dynamic Field

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

仕組み​

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

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

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

たとえば、コレクションスキーマで id と vector のみを定義し、次のエンティティを挿入するとします。

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"
}
}

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

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

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

  • エンティティごとに異なるメタデータのキャプチャ

  • 特定の dynamic field キーへのインデックスによる柔軟なフィルタリングのサポート

サポートされるデータ型​

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

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

  • 文字列 (VARCHAR)

  • 整数 (INT8, INT32, INT64)

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

  • ブール値 (BOOL)

  • スカラー値の配列 (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 機能を使用するには、コレクションスキーマの作成時に 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
)

コレクションにエンティティを挿入する​

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 内の特定のキーにインデックスを作成できます。これらのキーは、スカラー値または JSON オブジェクト内のネストされた値です。

Notes

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

JSON path indexing の構文​

JSON path インデックスを作成するには、次の項目を指定します。

  • 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 フィールドであるため、JSON path 構文を使用してその中の任意のキーにインデックスを作成できます。これは、単純なスカラー値と複雑なネスト構造の両方で機能します。

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
}
)
Notes
  • 型変換に失敗した場合(たとえば値 "not_a_number" を数値に変換できない場合)、その値はスキップされ、インデックスは作成されません。

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

コレクションにインデックスを適用する​

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

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

dynamic field キーによるフィルタリング​

dynamic field キーを持つエンティティを挿入した後は、標準のフィルタ式を使用してそれらをフィルタリングできます。

  • JSON 以外のキー(文字列、数値、ブール値など)は、キー名を直接参照して使用できます。

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

前のセクションのこのエンティティ例に基づくと、有効なフィルタ式には次のものが含まれます。

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 キーの取得: 検索またはクエリの結果で dynamic field キーを返すには、フィルタリングと同じ 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
]
)
Notes

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

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

まとめ​

ここまでで、スキーマで定義されていないキーを柔軟に保存し、インデックスを作成するために dynamic field を使用する方法を学習しました。dynamic field キーを挿入した後は、特別な構文を使用せずに、他のフィールドと同様にフィルタ式で使用できます。

実際のアプリケーションでワークフローを完了するには、次のことも必要です。

  • ベクトルフィールドにインデックスを作成する(各コレクションで必須)

    詳細については、AUTOINDEX Explained と関連ページを参照してください。

  • コレクションをロードする

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

  • JSON path フィルタを使用して検索またはクエリを実行する

    詳細については、Filtered Search と JSON Operators を参照してください。

FAQ​

dynamic field キーを使用する代わりに、スキーマでフィールドを明示的に定義する必要があるのはどのような場合ですか?​

次のような場合は、dynamic field キーを使用する代わりに、スキーマでフィールドを明示的に定義することをお勧めします。

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

  • フィールドへのアクセスやフィルタリングが頻繁に行われる場合: dynamic field キーにインデックスを作成すると固定スキーマフィールドと同程度のフィルタリングパフォーマンスが得られますが、明示的に定義されたフィールドの方が構造が明確で保守性に優れています。

  • フィールドの動作を完全に制御する必要がある場合: 明示的なフィールドはスキーマレベルの制約、検証、より明確な型指定をサポートしており、データの整合性と一貫性の管理に役立ちます。

  • インデックスの不整合を回避したい場合: dynamic field キー内のデータは、型や構造に不整合が生じやすくなります。固定スキーマを使用すると、特にインデックス作成や cast を計画している場合に、データ品質を確保しやすくなります。

dynamic field キーを既存のコレクションの明示的なスカラーフィールドにする場合は、コレクションスキーマの変更 を参照してください。既存のコレクションレベルの dynamic field 設定はコレクションプロパティで管理されます。詳細については、コレクションの変更 を参照してください。

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

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

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

dynamic field キーにインデックスを作成した後でデータの cast に失敗した場合(たとえば double に cast する予定の値が "abc" のような数値以外の文字列である場合)、それらの値はインデックス作成時に通知なしにスキップされます。これらの値はインデックスに含まれないため、インデックスに依存するフィルタベースの検索またはクエリの結果には返されません。

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

  • フルスキャンへのフォールバックは行われない: 大多数のエンティティのインデックス作成が成功した場合、フィルタリングクエリはインデックスのみに依存します。cast に失敗したエンティティは、フィルタ条件に論理的に一致していても結果セットから除外されます。

  • 検索精度のリスク: データ品質が一貫していない大規模なデータセット(特に dynamic field キー)では、この動作によって予期しない結果の欠落が発生する可能性があります。インデックスを作成する前に、一貫性のある有効なデータ形式を確保することが重要です。

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

クエリで、インデックス作成時の cast 型とは異なるデータ型を使用するとどうなりますか?​

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