Nullable & Default
Zilliz Cloudでは、プライマリフィールドを除くスカラーフィールドに対してnullable属性とデフォルト値を設定できます。nullable=Trueとマークされたフィールドの場合、データ挿入時にフィールドをスキップするか、直接null値に設定でき、システムはエラーを発生させずにnullとして扱います。フィールドにデフォルト値がある場合、挿入時にフィールドのデータが指定されていないとシステムは自動的にこの値を適用します。
デフォルト値とnullable属性により、他のデータベースシステムからZilliz Cloudへのデータ移行が容易になり、null値を含むデータセットの処理やデフォルト値設定の保持が可能になります。コレクション作成時には、値が不明確なフィールドに対してnullableを有効にしたり、デフォルト値を設定したりすることもできます。
制限事項
-
プライマリフィールドを除くスカラーフィールドのみがデフォルト値とnullable属性をサポートします。
-
JSONフィールドとArrayフィールドはデフォルト値をサポートしません。
-
デフォルト値またはnullable属性はコレクション作成時にのみ設定でき、以降は変更できません。
-
nullable属性が有効になっているスカラーフィールドは、グループ検索の
group_by_fieldとして使用できません。グループ検索の詳細については、グループ検索を参照してください。 -
nullableとしてマークされたフィールドはパーティションキーとして使用できません。パーティションキーの詳細については、パーティションキーの使用方法を参照してください。
-
nullable属性が有効になっているスカラーフィールドにインデックスを作成する場合、null値はインデックスから除外されます。
-
JSONおよびARRAYフィールド: JSONまたはARRAYフィールドに対して
IS NULLまたはIS NOT NULL演算子を使用してフィルタリングする場合、これらの演算子はカラムレベルで動作し、つまりJSONオブジェクト全体または配列がnullかどうかのみ評価することを意味します。たとえば、JSONオブジェクト内のキーがnullであれば、IS NULLフィルタでは認識されません。詳細については、基本演算子を参照してください。
Nullable属性
nullable属性により、null値をコレクションに保存でき、不明なデータを処理する際の柔軟性を提供します。
Nullable属性の設定
コレクション作成時に、nullable=Trueを使用してnullableフィールドを定義します(デフォルトはFalse)。「my_collection」という名前のコレクションを作成し、ageフィールドをnullableに設定する例を以下に示します。
- Python
- Java
- NodeJS
- Go
- cURL
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri='YOUR_CLUSTER_ENDPOINT')
# コレクションスキーマを定義
schema = client.create_schema(
auto_id=False,
enable_dynamic_schema=True,
)
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5)
schema.add_field(field_name="age", datatype=DataType.INT64, nullable=True) # Nullableフィールド
# インデックスパラメータを設定
index_params = client.prepare_index_params()
index_params.add_index(field_name="vector", index_type="AUTOINDEX", metric_type="L2")
# コレクションを作成
client.create_collection(collection_name="my_collection", schema=schema, index_params=index_params)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.DataType;
import io.milvus.v2.common.IndexParam;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
import java.util.*;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.build());
CreateCollectionReq.CollectionSchema schema = client.createSchema();
schema.setEnableDynamicField(true);
schema.addField(AddFieldReq.builder()
.fieldName("id")
.dataType(DataType.Int64)
.isPrimaryKey(true)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("vector")
.dataType(DataType.FloatVector)
.dimension(5)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("age")
.dataType(DataType.Int64)
.isNullable(true)
.build());
List<IndexParam> indexes = new ArrayList<>();
Map<String,Object> extraParams = new HashMap<>();
indexes.add(IndexParam.builder()
.fieldName("vector")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.L2)
.build());
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.indexParams(indexes)
.build();
client.createCollection(requestCreate);
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({
address: "YOUR_CLUSTER_ENDPOINT",
token: "YOUR_CLUSTER_TOKEN",
});
await client.createCollection({
collection_name: "my_collection",
schema: [
{
name: "id",
is_primary_key: true,
data_type: DataType.int64,
},
{ name: "vector", data_type: DataType.Int64, dim: 5 },
{ name: "age", data_type: DataType.FloatVector, nullable: true },
],
index_params: [
{
index_name: "vector_inde",
field_name: "vector",
metric_type: MetricType.L2,
index_type: IndexType.AUTOINDEX,
},
],
});
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v2/column"
"github.com/milvus-io/milvus/client/v2/entity"
"github.com/milvus-io/milvus/client/v2/index"
"github.com/milvus-io/milvus/client/v2/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
milvusAddr := "YOUR_CLUSTER_ENDPOINT"
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: milvusAddr,
})
if err != nil {
fmt.Println(err.Error())
// エラー処理
}
defer client.Close(ctx)
schema := entity.NewSchema()
schema.WithField(entity.NewField().
WithName("id").
WithDataType(entity.FieldTypeInt64).
WithIsPrimaryKey(true),
).WithField(entity.NewField().
WithName("vector").
WithDataType(entity.FieldTypeFloatVector).
WithDim(5),
).WithField(entity.NewField().
WithName("age").
WithDataType(entity.FieldTypeInt64).
WithNullable(true),
)
indexOption := milvusclient.NewCreateIndexOption("my_collection", "vector",
index.NewAutoIndex(index.MetricType(entity.L2)))
err = client.CreateCollection(ctx,
milvusclient.NewCreateCollectionOption("my_collection", schema).
WithIndexOptions(indexOption))
if err != nil {
fmt.Println(err.Error())
// エラー処理
}
export pkField='{
"fieldName": "id",
"dataType": "Int64",
"isPrimary": true
}'
export vectorField='{
"fieldName": "vector",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": 5
}
}'
export nullField='{
"fieldName": "age",
"dataType": "Int64",
"nullable": true
}'
export schema="{
\"autoID\": false,
\"fields\": [
$pkField,
$vectorField,
$nullField
]
}"
export indexParams='[
{
"fieldName": "vector",
"metricType": "L2",
"indexType": "AUTOINDEX"
}
]'
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
\"collectionName\": \"my_collection\",
\"schema\": $schema,
\"indexParams\": $indexParams
}"
エンティティの挿入
nullableフィールドにデータを挿入する際には、nullを挿入するか、このフィールドを直接省略します。
- Python
- Java
- NodeJS
- Go
- cURL
data = [
{"id": 1, "vector": [0.1, 0.2, 0.3, 0.4, 0.5], "age": 30},
{"id": 2, "vector": [0.2, 0.3, 0.4, 0.5, 0.6], "age": None},
{"id": 3, "vector": [0.3, 0.4, 0.5, 0.6, 0.7]}
]
client.insert(collection_name="my_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("{\"id\": 1, \"vector\": [0.1, 0.2, 0.3, 0.4, 0.5], \"age\": 30}", JsonObject.class));
rows.add(gson.fromJson("{\"id\": 2, \"vector\": [0.2, 0.3, 0.4, 0.5, 0.6], \"age\": null}", JsonObject.class));
rows.add(gson.fromJson("{\"id\": 3, \"vector\": [0.3, 0.4, 0.5, 0.6, 0.7]}", JsonObject.class));
InsertResp insertR = client.insert(InsertReq.builder()
.collectionName("my_collection")
.data(rows)
.build());
const data = [
{ id: 1, vector: [0.1, 0.2, 0.3, 0.4, 0.5], age: 30 },
{ id: 2, vector: [0.2, 0.3, 0.4, 0.5, 0.6], age: null },
{ id: 3, vector: [0.3, 0.4, 0.5, 0.6, 0.7] },
];
client.insert({
collection_name: "my_collection",
data: data,
});
column, _ := column.NewNullableColumnInt64("age",
[]int64{30},
[]bool{true, false, false})
_, err = client.Insert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection").
WithInt64Column("id", []int64{1, 2, 3}).
WithFloatVectorColumn("vector", 5, [][]float32{
{0.1, 0.2, 0.3, 0.4, 0.5},
{0.2, 0.3, 0.4, 0.5, 0.6},
{0.3, 0.4, 0.5, 0.6, 0.7},
}).
WithColumns(column),
)
if err != nil {
fmt.Println(err.Error())
// エラー処理
}
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"data": [
{"id": 1, "vector": [0.1, 0.2, 0.3, 0.4, 0.5], "age": 30},
{"id": 2, "vector": [0.2, 0.3, 0.4, 0.5, 0.6], "age": null},
{"id": 3, "vector": [0.3, 0.4, 0.5, 0.6, 0.7]}
],
"collectionName": "my_collection"
}'
null値を使用した検索とクエリ
searchメソッドを使用する際、フィールドにnull値が含まれている場合、検索結果はフィールドをnullとして返します。
- Python
- Java
- NodeJS
- Go
- cURL
res = client.search(
collection_name="my_collection",
data=[[0.1, 0.2, 0.4, 0.3, 0.128]],
limit=2,
search_params={"params": {"nprobe": 16}},
output_fields=["id", "age"]
)
print(res)
# 出力
# data: ["[{'id': 1, 'distance': 0.15838398039340973, 'entity': {'age': 30, 'id': 1}}, {'id': 2, 'distance': 0.28278401494026184, 'entity': {'age': None, 'id': 2}}]"]
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;
Map<String,Object> params = new HashMap<>();
params.put("nprobe", 16);
SearchResp resp = client.search(SearchReq.builder()
.collectionName("my_collection")
.annsField("vector")
.data(Collections.singletonList(new FloatVec(new float[]{0.1f, 0.2f, 0.3f, 0.4f, 0.5f})))
.topK(2)
.searchParams(params)
.outputFields(Arrays.asList("id", "age"))
.build());
System.out.println(resp.getSearchResults());
// 出力
//
// [[SearchResp.SearchResult(entity={id=1, age=30}, score=0.0, id=1), SearchResp.SearchResult(entity={id=2, age=null}, score=0.050000004, id=2)]]
client.search({
collection_name: 'my_collection',
data: [0.3, -0.6, 0.1, 0.3, 0.5],
limit: 2,
output_fields: ['age', 'id'],
params: {
nprobe: 16
}
});
queryVector := []float32{0.1, 0.2, 0.4, 0.3, 0.128}
annParam := index.NewCustomAnnParam()
annParam.WithExtraParam("nprobe", 16)
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
"my_collection", // collectionName
2, // limit
[]entity.Vector{entity.FloatVector(queryVector)},
).WithANNSField("vector").
WithAnnParam(annParam).
WithOutputFields("id", "age"))
if err != nil {
fmt.Println(err.Error())
// エラー処理
}
for _, resultSet := range resultSets {
fmt.Println("IDs: ", resultSet.IDs.FieldData().GetScalars())
fmt.Println("Scores: ", resultSet.Scores)
fmt.Println("age: ", resultSet.GetColumn("age").FieldData().GetScalars())
}
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"data": [
[0.1, -0.2, 0.3, 0.4, 0.5]
],
"annsField": "vector",
"limit": 2,
"outputFields": ["id", "age"]
}'
#{"code":0,"cost":0,"data":[{"age":30,"distance":0.16000001,"id":1},{"age":null,"distance":0.28999996,"id":2}]}
queryメソッドを使用してスカラーフィルタリングを行う場合、null値のフィルタリング結果はすべてfalseになり、つまり選択されません。
- Python
- Java
- NodeJS
- Go
- cURL
# 以前に挿入されたデータの確認:
# {"id": 1, "vector": [0.1, 0.2, ..., 0.128], "age": 30}
# {"id": 2, "vector": [0.2, 0.3, ..., 0.129], "age": None}
# {"id": 3, "vector": [0.3, 0.4, ..., 0.130], "age": None} # 省略されたageカラムはNoneとして扱われる
results = client.query(
collection_name="my_collection",
filter="age >= 0",
output_fields=["id", "age"]
)
# 例の出力:
# [
# {"id": 1, "age": 30}
# ]
# 注:`age`が`null`であるエンティティ(id 2および3)は結果に表示されません。
import io.milvus.v2.service.vector.request.QueryReq;
import io.milvus.v2.service.vector.response.QueryResp;
QueryResp resp = client.query(QueryReq.builder()
.collectionName("my_collection")
.filter("age >= 0")
.outputFields(Arrays.asList("id", "age"))
.build());
System.out.println(resp.getQueryResults());
// 出力
//
// [QueryResp.QueryResult(entity={id=1, age=30})]
const results = await client.query(
collection_name: "my_collection",
filter: "age >= 0",
output_fields: ["id", "age"]
);
resultSet, err := client.Query(ctx, milvusclient.NewQueryOption("my_collection").
WithFilter("age >= 0").
WithOutputFields("id", "age"))
if err != nil {
fmt.Println(err.Error())
// エラー処理
}
fmt.Println("id: ", resultSet.GetColumn("id").FieldData().GetScalars())
fmt.Println("age: ", resultSet.GetColumn("age").FieldData().GetScalars())
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"filter": "age >= 0",
"outputFields": ["id", "age"]
}'
# {"code":0,"cost":0,"data":[{"age":30,"id":1}]}
null値を持つエンティティを返すには、以下のようにスカラーのフィルタリング条件なしでクエリを実行します。
フィルタリング条件なしでqueryメソッドを使用すると、null値を持つものを含むコレクション内のすべてのエンティティを取得します。返されるエンティティの数を制限するには、limitパラメータを指定する必要があります。
- Python
- Java
- NodeJS
- Go
- cURL
null_results = client.query(
collection_name="my_collection",
filter="", # フィルタリング条件なしでクエリを実行
output_fields=["id", "age"],
limit=10
)
# 例の出力:
# [{"id": 2, "age": None}, {"id": 3, "age": None}]
QueryResp resp = client.query(QueryReq.builder()
.collectionName("my_collection")
.filter("")
.outputFields(Arrays.asList("id", "age"))
.limit(10)
.build());
System.out.println(resp.getQueryResults());
const results = await client.query(
collection_name: "my_collection",
filter: "",
output_fields: ["id", "age"],
limit: 10
);
resultSet, err = client.Query(ctx, milvusclient.NewQueryOption("my_collection").
WithFilter("").
WithLimit(10).
WithOutputFields("id", "age"))
if err != nil {
fmt.Println(err.Error())
// エラー処理
}
fmt.Println("id: ", resultSet.GetColumn("id"))
fmt.Println("age: ", resultSet.GetColumn("age"))
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"expr": "",
"outputFields": ["id", "age"],
"limit": 10
}'
# {"code":0,"cost":0,"data":[{"age":30,"id":1},{"age":null,"id":2},{"age":null,"id":3}]}
デフォルト値
デフォルト値は、スカラーフィールドに割り当てられる事前設定された値です。挿入時にデフォルト値を持つフィールドの値を指定しない場合、システムは自動的にデフォルト値を使用します。
デフォルト値の設定
コレクション作成時に、default_valueパラメータを使用してフィールドのデフォルト値を定義します。以下の例では、ageのデフォルト値を18に、statusのデフォルト値を"active"に設定する方法を示しています。
- Python
- Java
- NodeJS
- Go
- cURL
schema = client.create_schema(
auto_id=False,
enable_dynamic_schema=True,
)
schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True)
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5)
schema.add_field(field_name="age", datatype=DataType.INT64, default_value=18)
schema.add_field(field_name="status", datatype=DataType.VARCHAR, default_value="active", max_length=10)
index_params = client.prepare_index_params()
index_params.add_index(field_name="vector", index_type="AUTOINDEX", metric_type="L2")
client.create_collection(collection_name="my_collection", schema=schema, index_params=index_params)
import io.milvus.v2.common.DataType;
import io.milvus.v2.common.IndexParam;
import io.milvus.v2.service.collection.request.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
import java.util.*;
CreateCollectionReq.CollectionSchema schema = client.createSchema();
schema.setEnableDynamicField(true);
schema.addField(AddFieldReq.builder()
.fieldName("id")
.dataType(DataType.Int64)
.isPrimaryKey(true)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("vector")
.dataType(DataType.FloatVector)
.dimension(5)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("age")
.dataType(DataType.Int64)
.defaultValue(18L)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("status")
.dataType(DataType.VarChar)
.maxLength(10)
.defaultValue("active")
.build());
List<IndexParam> indexes = new ArrayList<>();
Map<String,Object> extraParams = new HashMap<>();
indexes.add(IndexParam.builder()
.fieldName("vector")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.L2)
.build());
CreateCollectionReq requestCreate = CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.indexParams(indexes)
.build();
client.createCollection(requestCreate);
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({
address: "YOUR_CLUSTER_ENDPOINT",
token: "YOUR_CLUSTER_TOKEN",
});
await client.createCollection({
collection_name: "my_collection",
schema: [
{
name: "id",
is_primary_key: true,
data_type: DataType.int64,
},
{ name: "vector", data_type: DataType.FloatVector, dim: 5 },
{ name: "age", data_type: DataType.Int64, default_value: 18 },
{ name: 'status', data_type: DataType.VarChar, max_length: 30, default_value: 'active'},
],
index_params: [
{
index_name: "vector_inde",
field_name: "vector",
metric_type: MetricType.L2,
index_type: IndexType.AUTOINDEX,
},
],
});
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v2/column"
"github.com/milvus-io/milvus/client/v2/entity"
"github.com/milvus-io/milvus/client/v2/index"
"github.com/milvus-io/milvus/client/v2/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
milvusAddr := "YOUR_CLUSTER_ENDPOINT"
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: milvusAddr,
})
if err != nil {
fmt.Println(err.Error())
// エラー処理
}
schema := entity.NewSchema()
schema.WithField(entity.NewField().
WithName("id").
WithDataType(entity.FieldTypeInt64).
WithIsPrimaryKey(true),
).WithField(entity.NewField().
WithName("vector").
WithDataType(entity.FieldTypeFloatVector).
WithDim(5),
).WithField(entity.NewField().
WithName("age").
WithDataType(entity.FieldTypeInt64).
WithDefaultValueLong(18),
).WithField(entity.NewField().
WithName("status").
WithDataType(entity.FieldTypeVarChar).
WithMaxLength(10).
WithDefaultValueString("active"),
)
indexOption := milvusclient.NewCreateIndexOption("my_collection", "vector",
index.NewAutoIndex(index.MetricType(entity.L2)))
err = client.CreateCollection(ctx,
milvusclient.NewCreateCollectionOption("my_collection", schema).
WithIndexOptions(indexOption))
if err != nil {
fmt.Println(err.Error())
// エラー処理
}
export pkField='{
"fieldName": "id",
"dataType": "Int64",
"isPrimary": true
}'
export vectorField='{
"fieldName": "vector",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": 5
}
}'
export defaultValueField1='{
"fieldName": "age",
"dataType": "Int64",
"defaultValue": 18
}'
export defaultValueField2='{
"fieldName": "status",
"dataType": "VarChar",
"defaultValue": "active",
"elementTypeParams": {
"max_length": 10
}
}'
export schema="{
\"autoID\": false,
\"fields\": [
$pkField,
$vectorField,
$defaultValueField1,
$defaultValueField2
]
}"
export indexParams='[
{
"fieldName": "vector",
"metricType": "L2",
"indexType": "AUTOINDEX"
}
]'
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
\"collectionName\": \"my_collection\",
\"schema\": $schema,
\"indexParams\": $indexParams
}"
エンティティの挿入
データを挿入する際、デフォルト値を持つフィールドを省略するか、その値をnullに設定すると、システムはデフォルト値を使用します。
- Python
- Java
- NodeJS
- Go
- cURL
data = [
{"id": 1, "vector": [0.1, 0.2, ..., 0.128], "age": 30, "status": "premium"},
{"id": 2, "vector": [0.2, 0.3, ..., 0.129]}, # `age`と`status`はデフォルト値を使用
{"id": 3, "vector": [0.3, 0.4, ..., 0.130], "age": 25, "status": None}, # `status`はデフォルト値を使用
{"id": 4, "vector": [0.4, 0.5, ..., 0.131], "age": None, "status": "inactive"} # `age`はデフォルト値を使用
]
client.insert(collection_name="my_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("{\"id\": 1, \"vector\": [0.1, 0.2, 0.3, 0.4, 0.5], \"age\": 30, \"status\": \"premium\"}", JsonObject.class));
rows.add(gson.fromJson("{\"id\": 2, \"vector\": [0.2, 0.3, 0.4, 0.5, 0.6]}", JsonObject.class));
rows.add(gson.fromJson("{\"id\": 3, \"vector\": [0.3, 0.4, 0.5, 0.6, 0.7], \"age\": 25, \"status\": null}", JsonObject.class));
rows.add(gson.fromJson("{\"id\": 4, \"vector\": [0.4, 0.5, 0.6, 0.7, 0.8], \"age\": null, \"status\": \"inactive\"}", JsonObject.class));
InsertResp insertR = client.insert(InsertReq.builder()
.collectionName("my_collection")
.data(rows)
.build());
const data = [
{"id": 1, "vector": [0.1, 0.2, 0.3, 0.4, 0.5], "age": 30, "status": "premium"},
{"id": 2, "vector": [0.2, 0.3, 0.4, 0.5, 0.6]},
{"id": 3, "vector": [0.3, 0.4, 0.5, 0.6, 0.7], "age": 25, "status": null},
{"id": 4, "vector": [0.4, 0.5, 0.6, 0.7, 0.8], "age": null, "status": "inactive"}
];
client.insert({
collection_name: "my_collection",
data: data,
});
column1, _ := column.NewNullableColumnInt64("age",
[]int64{30, 25},
[]bool{true, false, true, false})
column2, _ := column.NewNullableColumnVarChar("status",
[]string{"premium", "inactive"},
[]bool{true, false, false, true})
_, err = client.Insert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection").
WithInt64Column("id", []int64{1, 2, 3, 4}).
WithFloatVectorColumn("vector", 5, [][]float32{
{0.1, 0.2, 0.3, 0.4, 0.5},
{0.2, 0.3, 0.4, 0.5, 0.6},
{0.3, 0.4, 0.5, 0.6, 0.7},
{0.4, 0.5, 0.6, 0.7, 0.8},
}).
WithColumns(column1, column2),
)
if err != nil {
fmt.Println(err.Error())
// エラー処理
}
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"data": [
{"id": 1, "vector": [0.1, 0.2, 0.3, 0.4, 0.5], "age": 30, "status": "premium"},
{"id": 2, "vector": [0.2, 0.3, 0.4, 0.5, 0.6]},
{"id": 3, "vector": [0.3, 0.4, 0.5, 0.6, 0.7], "age": 25, "status": null},
{"id": 4, "vector": [0.4, 0.5, 0.6, 0.7, 0.8], "age": null, "status": "inactive"}
],
"collectionName": "my_collection"
}'
nullableとデフォルト値の設定がどのように効果を発揮するかの詳細については、適用ルールを参照してください。
デフォルト値を使用した検索とクエリ
デフォルト値を含むエンティティは、ベクトル検索やスカラーフィルタリング中に他のエンティティと同じように扱われます。検索やクエリ操作の一部としてデフォルト値を含めることができます。
たとえば、search操作では、ageが18のデフォルト値に設定されているエンティティは結果に含まれます。
- Python
- Java
- NodeJS
- Go
- cURL
res = client.search(
collection_name="my_collection",
data=[[0.1, 0.2, 0.4, 0.3, 0.5]],
search_params={"params": {"nprobe": 16}},
filter="age == 18", # 18は`age`フィールドのデフォルト値
limit=10,
output_fields=["id", "age", "status"]
)
print(res)
# 出力
# data: ["[{'id': 2, 'distance': 0.050000004, 'entity': {'id': 2, 'age': 18, 'status': 'active'}}, {'id': 4, 'distance': 0.45000002, 'entity': {'id': 4, 'age': 18, 'status': 'inactive'}}]"]
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;
Map<String,Object> params = new HashMap<>();
params.put("nprobe", 16);
SearchResp resp = client.search(SearchReq.builder()
.collectionName("my_collection")
.annsField("vector")
.data(Collections.singletonList(new FloatVec(new float[]{0.1f, 0.2f, 0.3f, 0.4f, 0.5f})))
.searchParams(params)
.filter("age == 18")
.topK(10)
.outputFields(Arrays.asList("id", "age", "status"))
.build());
System.out.println(resp.getSearchResults());
// 出力
//
// [[SearchResp.SearchResult(entity={id=2, age=18, status=active}, score=0.050000004, id=2), SearchResp.SearchResult(entity={id=4, age=18, status=inactive}, score=0.45000002, id=4)]]
client.search({
collection_name: 'my_collection',
data: [0.3, -0.6, 0.1, 0.3, 0.5],
limit: 2,
output_fields: ['age', 'id', 'status'],
filter: 'age == 18',
params: {
nprobe: 16
}
});
queryVector := []float32{0.1, 0.2, 0.4, 0.3, 0.5}
annParam := index.NewCustomAnnParam()
annParam.WithExtraParam("nprobe", 16)
resultSets, err := client.Search(ctx, milvusclient.NewSearchOption(
"my_collection", // collectionName
10, // limit
[]entity.Vector{entity.FloatVector(queryVector)},
).WithANNSField("vector").
WithFilter("age == 18").
WithAnnParam(annParam).
WithOutputFields("id", "age", "status"))
if err != nil {
fmt.Println(err.Error())
// エラー処理
}
for _, resultSet := range resultSets {
fmt.Println("IDs: ", resultSet.IDs.FieldData().GetScalars())
fmt.Println("Scores: ", resultSet.Scores)
fmt.Println("age: ", resultSet.GetColumn("age").FieldData().GetScalars())
fmt.Println("status: ", resultSet.GetColumn("status").FieldData().GetScalars())
}
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/search" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"data": [
[0.1, 0.2, 0.3, 0.4, 0.5]
],
"annsField": "vector",
"limit": 10,
"filter": "age == 18",
"outputFields": ["id", "age", "status"]
}'
# {"code":0,"cost":0,"data":[{"age":18,"distance":0.050000004,"id":2,"status":"active"},{"age":18,"distance":0.45000002,"id":4,"status":"inactive"}]}
query操作では、デフォルト値を直接照合またはフィルタリングできます。
- Python
- Java
- NodeJS
- Go
- cURL
# `age`がデフォルト値(18)と等しいすべてのエンティティをクエリ
default_age_results = client.query(
collection_name="my_collection",
filter="age == 18",
output_fields=["id", "age", "status"]
)
# `status`がデフォルト値("active")と等しいすべてのエンティティをクエリ
default_status_results = client.query(
collection_name="my_collection",
filter='status == "active"',
output_fields=["id", "age", "status"]
)
import io.milvus.v2.service.vector.request.QueryReq;
import io.milvus.v2.service.vector.response.QueryResp;
QueryResp ageResp = client.query(QueryReq.builder()
.collectionName("my_collection")
.filter("age == 18")
.outputFields(Arrays.asList("id", "age", "status"))
.build());
System.out.println(ageResp.getQueryResults());
// 出力
//
// [QueryResp.QueryResult(entity={id=2, age=18, status=active}), QueryResp.QueryResult(entity={id=4, age=18, status=inactive})]
QueryResp statusResp = client.query(QueryReq.builder()
.collectionName("my_collection")
.filter("status == \"active\"")
.outputFields(Arrays.asList("id", "age", "status"))
.build());
System.out.println(statusResp.getQueryResults());
// 出力
//
// [QueryResp.QueryResult(entity={id=2, age=18, status=active}), QueryResp.QueryResult(entity={id=3, age=25, status=active})]
// `age`がデフォルト値(18)と等しいすべてのエンティティをクエリ
const default_age_results = await client.query(
collection_name: "my_collection",
filter: "age == 18",
output_fields: ["id", "age", "status"]
);
// `status`がデフォルト値("active")と等しいすべてのエンティティをクエリ
const default_status_results = await client.query(
collection_name: "my_collection",
filter: 'status == "active"',
output_fields: ["id", "age", "status"]
)
resultSet, err := client.Query(ctx, milvusclient.NewQueryOption("my_collection").
WithFilter("age == 18").
WithOutputFields("id", "age", "status"))
if err != nil {
fmt.Println(err.Error())
// エラー処理
}
fmt.Println("id: ", resultSet.GetColumn("id").FieldData().GetScalars())
fmt.Println("age: ", resultSet.GetColumn("age").FieldData().GetScalars())
fmt.Println("status: ", resultSet.GetColumn("status").FieldData().GetScalars())
resultSet, err = client.Query(ctx, milvusclient.NewQueryOption("my_collection").
WithFilter("status == \"active\"").
WithOutputFields("id", "age", "status"))
if err != nil {
fmt.Println(err.Error())
// エラー処理
}
fmt.Println("id: ", resultSet.GetColumn("id").FieldData().GetScalars())
fmt.Println("age: ", resultSet.GetColumn("age").FieldData().GetScalars())
fmt.Println("status: ", resultSet.GetColumn("status").FieldData().GetScalars())
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"filter": "age == 18",
"outputFields": ["id", "age", "status"]
}'
# {"code":0,"cost":0,"data":[{"age":18,"id":2,"status":"active"},{"age":18,"id":4,"status":"inactive"}]}
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"filter": "status == \"active\"",
"outputFields": ["id", "age", "status"]
}'
# {"code":0,"cost":0,"data":[{"age":18,"id":2,"status":"active"},{"age":25,"id":3,"status":"active"}]}
適用ルール
以下の表は、nullable列とデフォルト値が異なる設定の組み合わせで動作する際の概要をまとめています。これらのルールは、null値を挿入しようとしたときやフィールド値が提供されない場合に、Zilliz Cloudがデータをどのように処理するかを決定します。
Nullable | デフォルト値 | デフォルト値の型 | ユーザー入力 | 結果 | 例 |
|---|---|---|---|---|---|
✅ | ✅ | Non-null | None/null | デフォルト値を使用 | フィールド: デフォルト値: ユーザー入力: null 結果: |
✅ | ❌ | - | None/null | nullとして格納 | フィールド: デフォルト値: - ユーザー入力: null 結果: nullとして格納 |
❌ | ✅ | Non-null | None/null | デフォルト値を使用 | フィールド: デフォルト値: ユーザー入力: null 結果: |
❌ | ❌ | - | None/null | エラーをスロー | フィールド: デフォルト値: - ユーザー入力: null 結果: 操作が拒否され、システムはエラーをスロー |
❌ | ✅ | Null | None/null | エラーをスロー | フィールド: デフォルト値: null ユーザー入力: null 結果: 操作が拒否され、システムはエラーをスロー |