数値フィールド
数値フィールドはmilvusのベクトル以外の数値データを格納するために使用されます。これらのフィールドは通常、年齢、価格などのベクトルデータに関連する追加情報を記述するために使用されます。このデータを使用することで、ベクトルをより適切に記述し、データフィルタリングや条件付きクエリの効率を向上させることができます。
数値フィールドは、多くのシナリオで特に有用です。たとえば、eコマースのレコメンデーションでは、価格フィールドをフィルタリングに使用できます。また、ユーザープロファイル分析では、年齢範囲が結果の絞り込みに役立ちます。ベクトルデータと組み合わせることで、数フィールドは、パーソナライズされたユーザーのニーズをより正確に満たしながら、システムが類似検索を提供するのに役立ちます。
サポートされる数値フィールドタイプ
Milvusは様々なデータ保存やクエリのニーズに対応するため、様々なタイプの数値フィールドをサポートしています。
タイプ | 説明 |
---|---|
|
|
| 8 ビット整数型。小さな範囲の整数データを格納するのに適している。 |
| 16 ビット整数。中範囲の整数データの格納に適する。 |
| 32ビット整数。製品数量やユーザーIDのような一般的な整数データの保存に最適。 |
| 64ビット整数。タイムスタンプや識別子のような大きな範囲のデータの保存に適しています。 |
| 32ビット浮動小数点数:定格や温度など、一般的な精度を必要とするデータ用。 |
| 64ビット倍精度浮動小数点数:金融情報や科学計算のような高精度データ用。 |
数値フィールドの追加
Milvusで数値フィールドを使用するには、コレクションスキーマで該当するフィールドを定義し、datatype
をBOOL
やINT8
のようなサポートされている型に設定します。サポートされる数値フィールドタイプの完全なリストは、サポートされる数値フィールドタイプを参照してください。
次の例は、数値フィールドage
とprice
を含むスキーマを定義する方法を示しています。
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530")
schema = client.create_schema(
auto_id=False,
enable_dynamic_fields=True,
)
schema.add_field(field_name="age", datatype=DataType.INT64)
schema.add_field(field_name="price", datatype=DataType.FLOAT)
schema.add_field(field_name="pk", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="embedding", datatype=DataType.FLOAT_VECTOR, dim=3)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.DataType;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.build());
CreateCollectionReq.CollectionSchema schema = client.createSchema();
schema.setEnableDynamicField(true);
schema.addField(AddFieldReq.builder()
.fieldName("age")
.dataType(DataType.Int64)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("price")
.dataType(DataType.Float)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("pk")
.dataType(DataType.Int64)
.isPrimaryKey(true)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("embedding")
.dataType(DataType.FloatVector)
.dimension(3)
.build());
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const schema = [
{
name: "age",
data_type: DataType.Int64,
},
{
name: "price",
data_type: DataType.Float,
},
{
name: "pk",
data_type: DataType.Int64,
is_primary_key: true,
},
{
name: "embedding",
data_type: DataType.FloatVector,
dim: 3,
},
];
export int64Field='{
"fieldName": "age",
"dataType": "Int64"
}'
export floatField='{
"fieldName": "price",
"dataType": "Float"
}'
export pkField='{
"fieldName": "pk",
"dataType": "Int64",
"isPrimary": true
}'
export vectorField='{
"fieldName": "embedding",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": 3
}
}'
export schema="{
\"autoID\": false,
\"fields\": [
$int64Field,
$floatField,
$pkField,
$vectorField
]
}"
プライマリフィールドとベクトルフィールドは、コレクションを作成するときに必須である。プライマリ・フィールドは各エンティティを一意に識別し、ベクター・フィールドは類似検索に重要である。詳細はPrimary Field & AutoID,Dense Vector,Binary Vector,Sparse Vector を参照。
インデックス・パラメータの設定
数値フィールドにインデックス・パラメータを設定することはオプションですが、検索効率を大幅に向上させることができます。
以下の例では、age
番号フィールドにAUTOINDEX
を作成し、Milvusがデータ型に基づいて適切なインデックスを自動的に作成できるようにしています。詳細はAUTOINDEXを参照してください。
index_params = client.prepare_index_params()
index_params.add_index(
field_name="age",
index_type="AUTOINDEX",
index_name="inverted_index"
)
import io.milvus.v2.common.IndexParam;
import java.util.*;
List<IndexParam> indexes = new ArrayList<>();
indexes.add(IndexParam.builder()
.fieldName("age")
.indexType(IndexParam.IndexType.AUTOINDEX)
.build());
const indexParams = {
index_name: 'inverted_index',
field_name: 'age',
index_type: IndexType.AUTOINDEX,
);
export indexParams='[
{
"fieldName": "age",
"indexName": "inverted_index",
"indexType": "AUTOINDEX"
}
]'
AUTOINDEX
以外にも、数値フィールドのインデックス・タイプを指定することができます。サポートされているインデックス・タイプについては、スカラー・インデックスを参照してください。
さらに、コレクションを作成する前に、ベクトル・フィールドのインデックスを作成する必要が あります。この例では、AUTOINDEX
を使用して、ベクトル・インデックスの設定を簡素化している。
# Add vector index
index_params.add_index(
field_name="embedding",
index_type="AUTOINDEX", # Use automatic indexing to simplify complex index settings
metric_type="COSINE" # Specify similarity metric type, options include L2, COSINE, or IP
)
indexes.add(IndexParam.builder()
.fieldName("embedding")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.COSINE)
.build());
import { IndexType } from "@zilliz/milvus2-sdk-node";
const indexParams = [
{
field_name: "age",
index_name: "inverted_index",
index_type: IndexType.AUTOINDEX,
},
{
field_name: "embedding",
metric_type: "COSINE",
index_type: IndexType.AUTOINDEX,
},
];
export indexParams='[
{
"fieldName": "age",
"indexName": "inverted_index",
"indexType": "AUTOINDEX"
},
{
"fieldName": "embedding",
"metricType": "COSINE",
"indexType": "AUTOINDEX"
}
]'
コレクションの作成
スキーマとインデックスが定義されたら、数値フィールドを含むコレクションを作成できます。
# Create Collection
client.create_collection(
collection_name="your_collection_name",
schema=schema,
index_params=index_params
)
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("my_scalar_collection")
.collectionSchema(schema)
.indexParams(indexes)
.build();
client.createCollection(requestCreate);
client.create_collection({
collection_name: "my_scalar_collection",
schema: schema,
index_params: indexParams
})
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
\"collectionName\": \"my_scalar_collection\",
\"schema\": $schema,
\"indexParams\": $indexParams
}"
データの挿入
コレクションを作成したら、数値フィールドを含むデータを挿入できます。
data = [
{"age": 25, "price": 99.99, "pk": 1, "embedding": [0.1, 0.2, 0.3]},
{"age": 30, "price": 149.50, "pk": 2, "embedding": [0.4, 0.5, 0.6]},
{"age": 35, "price": 199.99, "pk": 3, "embedding": [0.7, 0.8, 0.9]},
]
client.insert(
collection_name="my_scalar_collection",
data=data
)
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.milvus.v2.service.vector.request.InsertReq;
import io.milvus.v2.service.vector.response.InsertResp;
List<JsonObject> rows = new ArrayList<>();
Gson gson = new Gson();
rows.add(gson.fromJson("{\"age\": 25, \"price\": 99.99, \"pk\": 1, \"embedding\": [0.1, 0.2, 0.3]}", JsonObject.class));
rows.add(gson.fromJson("{\"age\": 30, \"price\": 149.50, \"pk\": 2, \"embedding\": [0.4, 0.5, 0.6]}", JsonObject.class));
rows.add(gson.fromJson("{\"age\": 35, \"price\": 199.99, \"pk\": 3, \"embedding\": [0.7, 0.8, 0.9]}", JsonObject.class));
InsertResp insertR = client.insert(InsertReq.builder()
.collectionName("my_scalar_collection")
.data(rows)
.build());
const data = [
{ age: 25, price: 99.99, pk: 1, embedding: [0.1, 0.2, 0.3] },
{ age: 30, price: 149.5, pk: 2, embedding: [0.4, 0.5, 0.6] },
{ age: 35, price: 199.99, pk: 3, embedding: [0.7, 0.8, 0.9] },
];
client.insert({
collection_name: "my_scalar_collection",
data: data,
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"data": [
{"age": 25, "price": 99.99, "pk": 1, "embedding": [0.1, 0.2, 0.3]},
{"age": 30, "price": 149.50, "pk": 2, "embedding": [0.4, 0.5, 0.6]},
{"age": 35, "price": 199.99, "pk": 3, "embedding": [0.7, 0.8, 0.9]}
],
"collectionName": "my_scalar_collection"
}'
この例では、age
、price
、pk
(主フィールド)、およびベクトル表現(embedding
)を含むデータを挿入します。挿入されたデータがスキーマで定義されたフィールドと一致していることを確認するために、エラーを避けるためにデータ型を事前にチェックすることをお勧めします。
スキーマ定義時にenable_dynamic_fields=True
を設定すると、milvusでは事前に定義されていない数値フィールドを挿入することができます。ただし、この場合、クエリや管理が複雑になり、パフォーマンスに影響を与える可能性があることに留意してください。詳細はDynamic Fieldを参照してください。
検索とクエリ
数値フィールドを追加した後は、検索やクエリ操作のフィルタリングに使用することで、より正確な検索結果を得ることができます。
フィルタ・クエリ
数値フィールドを追加すると、クエリでのフィルタリングに使用できます。たとえば、age
が 30 から 40 の間のすべてのエンティティを検索できます。
filter = "30 <= age <= 40"
res = client.query(
collection_name="my_scalar_collection",
filter=filter,
output_fields=["age","price"]
)
print(res)
# Output
# data: ["{'age': 30, 'price': np.float32(149.5), 'pk': 2}", "{'age': 35, 'price': np.float32(199.99), 'pk': 3}"]
import io.milvus.v2.service.vector.request.QueryReq;
import io.milvus.v2.service.vector.response.QueryResp;
String filter = "30 <= age <= 40";
QueryResp resp = client.query(QueryReq.builder()
.collectionName("my_scalar_collection")
.filter(filter)
.outputFields(Arrays.asList("age", "price"))
.build());
System.out.println(resp.getQueryResults());
// Output
//
// [QueryResp.QueryResult(entity={price=149.5, pk=2, age=30}), QueryResp.QueryResult(entity={price=199.99, pk=3, age=35})]
client.query({
collection_name: 'my_scalar_collection',
filter: '30 <= age <= 40',
output_fields: ['age', 'price']
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_scalar_collection",
"filter": "30 <= age <= 40",
"outputFields": ["age","price"]
}'
## {"code":0,"cost":0,"data":[{"age":30,"pk":2,"price":149.5},{"age":35,"pk":3,"price":199.99}]}
このクエリ式は、一致するすべてのエンティティを返し、それらのage
フィールドとprice
フィールドを出力します。フィルタ・クエリの詳細については、「メタデータ・フィルタリング」を参照してください。
数値フィルタリングによるベクトル検索
基本的な数値フィールド・フィルタリングに加えて、ベクトル類似性検索を数値フィールド・フィルタリングと組み合わせることができます。例えば、次のコードは、ベクトル検索に数値フィールド・フィルターを追加する方法を示しています。
filter = "25 <= age <= 35"
res = client.search(
collection_name="my_scalar_collection",
data=[[0.3, -0.6, 0.1]],
limit=5,
search_params={"params": {"nprobe": 10}},
output_fields=["age","price"],
filter=filter
)
print(res)
# Output
# data: ["[{'id': 1, 'distance': -0.06000000238418579, 'entity': {'age': 25, 'price': 99.98999786376953}}, {'id': 2, 'distance': -0.12000000476837158, 'entity': {'age': 30, 'price': 149.5}}, {'id': 3, 'distance': -0.18000000715255737, 'entity': {'age': 35, 'price': 199.99000549316406}}]"]
import io.milvus.v2.service.vector.request.SearchReq;
import io.milvus.v2.service.vector.request.data.FloatVec;
import io.milvus.v2.service.vector.response.SearchResp;
String filter = "25 <= age <= 35";
SearchResp resp = client.search(SearchReq.builder()
.collectionName("my_scalar_collection")
.annsField("embedding")
.data(Collections.singletonList(new FloatVec(new float[]{0.3f, -0.6f, 0.1f})))
.topK(5)
.outputFields(Arrays.asList("age", "price"))
.filter(filter)
.build());
System.out.println(resp.getSearchResults());
// Output
//
// [[SearchResp.SearchResult(entity={price=199.99, age=35}, score=-0.19054288, id=3), SearchResp.SearchResult(entity={price=149.5, age=30}, score=-0.20163085, id=2), SearchResp.SearchResult(entity={price=99.99, age=25}, score=-0.2364331, id=1)]]
client.search({
collection_name: 'my_scalar_collection',
data: [0.3, -0.6, 0.1],
limit: 5,
output_fields: ['age', 'price'],
filter: '25 <= age <= 35'
});
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_scalar_collection",
"data": [
[0.3, -0.6, 0.1]
],
"annsField": "embedding",
"limit": 5,
"outputFields": ["age", "price"]
}'
## {"code":0,"cost":0,"data":[{"age":35,"distance":-0.19054288,"id":3,"price":199.99},{"age":30,"distance":-0.20163085,"id":2,"price":149.5},{"age":25,"distance":-0.2364331,"id":1,"price":99.99}]}
この例では、まずクエリー・ベクターを定義し、検索中にフィルター条件(25 <= age <= 35
)を追加します。これにより、検索結果がクエリーベクトルに類似しているだけでなく、指定された年齢範囲も満たすようになります。詳細については、メタデータのフィルタリングを参照してください。