コレクションの TTL を設定する
Zilliz Cloud では、Time-to-Live(TTL) ポリシーを使用してエンティティを自動的に期限切れにできます。期限切れのエンティティはクエリおよび検索結果にすぐに表示されなくなり、次の Compaction サイクルでストレージから物理的に削除されます。通常、これは 24 時間以内に実行されます。
TTL には次の 2 つのモードがあります。
-
コレクションレベルの TTL — すべてのエンティティで共有される単一の保持期間です。
collection.ttl.secondsプロパティで設定します。 -
エンティティレベルの TTL — 各エンティティは、専用の
TIMESTAMPTZフィールドに独自の絶対有効期限を持ちます。このフィールドは、ttl_fieldプロパティによって TTL フィールドとして指定されます。
この機能はマネージドコレクションにのみ適用されます。
制限
-
2 つの TTL モードは相互に排他的です。コレクションで
collection.ttl.secondsとttl_fieldを同時に設定することはできません。切り替えるには、2 つのモード間の移行 を参照してください。 -
コレクションレベルの TTL は、コレクション全体に 1 つの保持期間を適用します。特定の行に異なる有効期間が必要な場合は、エンティティレベルの TTL を使用してください。
-
エンティティレベルの TTL に使用するフィールドは
TIMESTAMPTZである必要があります。その他の型は拒否されます。 -
コレクションごとに TTL フィールドは 1 つだけです。スキーマには複数の
TIMESTAMPTZフィールドを含めることができますが、ttl_fieldで指定できるのはそのうち 1 つだけです。 -
ttl_fieldを削除しても、期限切れのエンティティが再び表示されることはありません。期限切れのエンティティを復元するには、NULLまたは将来の有効期限タイムスタンプを指定して upsert してください。
概要
展開
TTL を使用する場合
保持が ポリシー である場合、TTL が適切な手段です。特定のエンティティが最終的に削除されるべきであることを事前に把握しており、cron ジョブを作成することなくクラスターにそのポリシーを適用したい場合に使用します。
一般的なシナリオは次のとおりです。
-
時間枠で区切られたデータセット。 ログ、メトリクス、イベント、または短命な特徴量キャッシュの直近 N 日分のみを保持します。
-
マルチテナントのコレクション。 同じコレクション内で、テナントごとに異なる保持期間を設定します。
-
レコード単位の保持ポリシー。 IoT パイプライン、ドキュメントストア、または MLOps 特徴量ストアで、ドキュメントごとの有効期間を設定します。
-
ホットデータとコールドデータの混在。 短命なエンティティと長期間保持するエンティティを同じコレクション内に共存させます。
-
コンプライアンスに基づく期限切れ。 各レコードが独自の「削除期限」を持つ、GDPR 形式のデータ最小化です。
-
ビジネス上の時刻に基づく期限切れ。 エンティティが、特定の絶対時点(キャンペーンの終了、セッションの期限切れなど)までのみ有効なレコードを表す場合に使用します。
期限切れのエンティティは、検索結果やクエリ結果に表示されません。ただし、後続のデータ Compaction が実行されるまでストレージに残る可能性があります。この Compaction は、次の 24 時間以内に実行される必要があります。
TTL モード
2 つのモードは、保持に関する異なる課題に対応します。
-
コレクションレベルの TTL は、すべてのエンティティに単一の保持期間を適用します。各エンティティは
insert_ts + ttl_secondsで期限切れになります。 -
エンティティレベルの TTL では、各エンティティが独自の絶対有効期限を
TIMESTAMPTZフィールドに保存できます。このフィールドの値がNULLの場合、そのエンティティは期限切れになりません。
コレクションは一度に 1 つ のモードを使用します。2 つのモードは相互に排他的です。モードの切り替えは複数の手順を必要とする操作です。2 つのモード間の移行を参照してください。
モードを選択するには、次の表を使用してください。
状況が次の場合… | 使用するモード |
|---|---|
コレクション内のすべてのエンティティが同じ保持期間に従う場合 | コレクションレベルの TTL |
保持期間が「挿入時点から N 秒間保持する」という条件である場合 | コレクションレベルの TTL |
同じコレクション内でエンティティごとに異なる有効期間が必要な場合(テナント別、hot/cold, ドキュメント別) | エンティティレベルの TTL |
保持期間が絶対的な実時刻(たとえば 2027-01-01T00:00:00Z)である場合 | エンティティレベルの TTL |
保持期間が挿入タイムスタンプではなくビジネス上のタイムスタンプに基づく場合 | エンティティレベルの TTL |
挿入後にエンティティの有効期間を更新または延長する場合 | エンティティレベルの TTL |
一部のエンティティは期限切れにせず、他のエンティティは期限切れにする場合 | エンティティレベルの TTL(期限切れにしないエンティティには NULL を使用) |
コレクションレベルの TTL を設定する
コレクション内のすべてのエンティティが同じ保持期間に従う場合は、コレクションレベルの TTL を使用してください。
新しいコレクションで有効にする
作成時に、collection.ttl.seconds(整数、秒単位)を properties マップで指定します。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT", token="YOUR_CLUSTER_TOKEN")
schema = client.create_schema(auto_id=False, enable_dynamic_field=False)
schema.add_field("id", DataType.INT64, is_primary=True, auto_id=False)
schema.add_field("vector", DataType.FLOAT_VECTOR, dim=128)
index_params = client.prepare_index_params()
index_params.add_index(
field_name="vector", index_type="AUTOINDEX", metric_type="COSINE"
)
client.create_collection(
collection_name="my_collection",
schema=schema,
index_params=index_params,
properties={
"collection.ttl.seconds": 1209600 # 14 days
},
)
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
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;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
CreateCollectionReq.CollectionSchema schema = CreateCollectionReq.CollectionSchema.builder().build();
schema.addField(AddFieldReq.builder().fieldName("id").dataType(DataType.Int64)
.isPrimaryKey(true).autoID(false).build());
schema.addField(AddFieldReq.builder().fieldName("vector").dataType(DataType.FloatVector)
.dimension(128).build());
IndexParam indexParam = IndexParam.builder().fieldName("vector")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.COSINE).build();
Map<String, String> properties = new HashMap<>();
properties.put("collection.ttl.seconds", "1209600"); // 14 days
client.createCollection(CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.indexParams(Collections.singletonList(indexParam))
.properties(properties)
.build());
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/common"
"github.com/milvus-io/milvus/client/v3/entity"
"github.com/milvus-io/milvus/client/v3/index"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
schema := entity.NewSchema().WithDynamicFieldEnabled(false).
WithField(entity.NewField().WithName("id").WithIsAutoID(false).WithDataType(entity.FieldTypeInt64).WithIsPrimaryKey(true)).
WithField(entity.NewField().WithName("vector").WithDataType(entity.FieldTypeFloatVector).WithDim(128))
indexOptions := []milvusclient.CreateIndexOption{
milvusclient.NewCreateIndexOption("my_collection", "vector", index.NewAutoIndex(entity.COSINE)),
}
err = client.CreateCollection(ctx, milvusclient.NewCreateCollectionOption("my_collection", schema).
WithIndexOptions(indexOptions...).
WithProperty(common.CollectionTTLConfigKey, 1209600)) // TTL in seconds
if err != nil {
fmt.Println(err.Error())
// handle error
}
use milvus::v2::prelude::*;
let client = ClientV2::new(&ConnectConfig::new()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")).await?;
let schema = CollectionSchema::new()
.enable_dynamic_field(false)
.add_field(FieldSchema::new().name("id").data_type(DataType::Int64).primary_key(true).auto_id(false))
.add_field(FieldSchema::new().name("vector").data_type(DataType::FloatVector).dimension(128));
let index_params = vec![
IndexParam::new().field_name("vector").index_type(IndexType::AutoIndex).metric_type(MetricType::Cosine),
];
client.create_collection(CreateCollectionRequest::builder()
.collection_name("my_collection")
.schema(schema)
.index_params(index_params)
.properties(std::collections::HashMap::from([("collection.ttl.seconds".to_string(), "1209600".to_string())]))
.build()?).await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("YOUR_CLUSTER_ENDPOINT").WithToken("YOUR_CLUSTER_TOKEN"));
milvus::CollectionSchemaPtr schema = std::make_shared<milvus::CollectionSchema>();
schema->AddField(milvus::FieldSchema("id", milvus::DataType::INT64, "", true, false));
schema->AddField(milvus::FieldSchema("vector", milvus::DataType::FLOAT_VECTOR).WithDimension(128));
std::vector<milvus::IndexDesc> indexes = {
milvus::IndexDesc("vector", "vector", milvus::IndexType::AUTOINDEX, milvus::MetricType::COSINE)};
status = client->CreateCollection(milvus::CreateCollectionRequest()
.WithCollectionName("my_collection")
.WithCollectionSchema(schema)
.WithIndexes(std::move(indexes))
.AddProperty(milvus::COLLECTION_TTL_SECONDS, "1209600"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
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",
fields: [
{ name: "id", data_type: DataType.Int64, is_primary_key: true, autoID: false },
{ name: "vector", data_type: DataType.FloatVector, dim: 128 },
],
index_params: [
{ field_name: "vector", index_type: "AUTOINDEX", metric_type: "COSINE" },
],
properties: {
"collection.ttl.seconds": 1209600, // 14 days
},
});
using Milvus.Client.V2;
using Milvus.Client.V2.Requests.Collection;
using Milvus.Client.V2.Types;
MilvusClientV2 client = new(new ConnectConfig
{
Uri = "YOUR_CLUSTER_ENDPOINT",
ApiKey = "YOUR_CLUSTER_TOKEN"
});
CollectionSchema schema = new()
{
EnableDynamicFields = false,
Fields =
{
new FieldSchema("id", DataType.Int64, isPrimaryKey: true),
new FieldSchema("vector", DataType.FloatVector) { Dimension = 128 }
}
};
await client.CreateCollectionAsync(new CreateCollectionReq
{
CollectionName = "my_collection",
Schema = schema,
Indexes = [new IndexParam("vector", null, IndexType.AutoIndex, MetricType.Cosine)],
Properties = { ["collection.ttl.seconds"] = "1209600" } // 14 days
});
export schema='{
"autoId": false,
"enableDynamicField": false,
"fields": [
{
"fieldName": "id",
"dataType": "Int64",
"isPrimary": true
},
{
"fieldName": "vector",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": "128"
}
}
]
}'
export indexParams='[
{
"fieldName": "vector",
"metricType": "COSINE",
"indexName": "vector",
"indexType": "AUTOINDEX"
}
]'
export params='{
"ttlSeconds": "1209600"
}'
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d "{
\"collectionName\": \"my_collection\",
\"schema\": $schema,
\"indexParams\": $indexParams,
\"params\": $params
}"
既存のコレクションで有効にする
使用中のコレクションに TTL を適用するには、properties マップで collection.ttl.seconds を指定して alter_collection_properties を呼び出します。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT", token="YOUR_CLUSTER_TOKEN")
# Assumes "my_collection" was created earlier without TTL
schema = client.create_schema(auto_id=False, enable_dynamic_field=False)
schema.add_field("id", DataType.INT64, is_primary=True, auto_id=False)
schema.add_field("vector", DataType.FLOAT_VECTOR, dim=128)
index_params = client.prepare_index_params()
index_params.add_index(
field_name="vector", index_type="AUTOINDEX", metric_type="COSINE"
)
if not client.has_collection("my_collection"):
client.create_collection(
collection_name="my_collection",
schema=schema,
index_params=index_params,
)
client.alter_collection_properties(
collection_name="my_collection",
properties={"collection.ttl.seconds": 1209600},
)
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
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.AlterCollectionPropertiesReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
import io.milvus.v2.service.collection.request.HasCollectionReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
// Assumes "my_collection" was created earlier without TTL.
if (!client.hasCollection(HasCollectionReq.builder().collectionName("my_collection").build())) {
CreateCollectionReq.CollectionSchema schema = CreateCollectionReq.CollectionSchema.builder().build();
schema.addField(AddFieldReq.builder().fieldName("id").dataType(DataType.Int64)
.isPrimaryKey(true).autoID(false).build());
schema.addField(AddFieldReq.builder().fieldName("vector").dataType(DataType.FloatVector)
.dimension(128).build());
IndexParam indexParam = IndexParam.builder().fieldName("vector")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.COSINE).build();
client.createCollection(CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.indexParams(Collections.singletonList(indexParam))
.build());
}
Map<String, String> properties = new HashMap<>();
properties.put("collection.ttl.seconds", "1209600");
client.alterCollectionProperties(AlterCollectionPropertiesReq.builder()
.collectionName("my_collection")
.properties(properties)
.build());
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/common"
"github.com/milvus-io/milvus/client/v3/entity"
"github.com/milvus-io/milvus/client/v3/index"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
// Assumes "my_collection" was created earlier without TTL.
exists, err := client.HasCollection(ctx, milvusclient.NewHasCollectionOption("my_collection"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
if !exists {
schema := entity.NewSchema().WithDynamicFieldEnabled(false).
WithField(entity.NewField().WithName("id").WithIsAutoID(false).WithDataType(entity.FieldTypeInt64).WithIsPrimaryKey(true)).
WithField(entity.NewField().WithName("vector").WithDataType(entity.FieldTypeFloatVector).WithDim(128))
indexOptions := []milvusclient.CreateIndexOption{
milvusclient.NewCreateIndexOption("my_collection", "vector", index.NewAutoIndex(entity.COSINE)),
}
err = client.CreateCollection(ctx, milvusclient.NewCreateCollectionOption("my_collection", schema).
WithIndexOptions(indexOptions...))
if err != nil {
fmt.Println(err.Error())
// handle error
}
}
err = client.AlterCollectionProperties(ctx, milvusclient.NewAlterCollectionPropertiesOption("my_collection").
WithProperty(common.CollectionTTLConfigKey, 1209600))
if err != nil {
fmt.Println(err.Error())
// handle error
}
use milvus::v2::prelude::*;
let client = ClientV2::new(&ConnectConfig::new()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")).await?;
let has = client.has_collection(HasCollectionRequest::builder()
.collection_name("my_collection")
.build()?).await?;
if !has.exists() {
let schema = CollectionSchema::new()
.enable_dynamic_field(false)
.add_field(FieldSchema::new().name("id").data_type(DataType::Int64).primary_key(true).auto_id(false))
.add_field(FieldSchema::new().name("vector").data_type(DataType::FloatVector).dimension(128));
let index_params = vec![
IndexParam::new().field_name("vector").index_type(IndexType::AutoIndex).metric_type(MetricType::Cosine),
];
client.create_collection(CreateCollectionRequest::builder()
.collection_name("my_collection")
.schema(schema)
.index_params(index_params)
.build()?).await?;
}
client.alter_collection_properties(AlterCollectionPropertiesRequest::builder()
.collection_name("my_collection")
.properties(std::collections::HashMap::from([("collection.ttl.seconds".to_string(), "1209600".to_string())]))
.build()?).await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("YOUR_CLUSTER_ENDPOINT").WithToken("YOUR_CLUSTER_TOKEN"));
milvus::HasCollectionResponse has_response;
status = client->HasCollection(milvus::HasCollectionRequest()
.WithCollectionName("my_collection"),
has_response);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
if (!has_response.Has()) {
milvus::CollectionSchemaPtr schema = std::make_shared<milvus::CollectionSchema>();
schema->AddField(milvus::FieldSchema("id", milvus::DataType::INT64, "", true, false));
schema->AddField(milvus::FieldSchema("vector", milvus::DataType::FLOAT_VECTOR).WithDimension(128));
std::vector<milvus::IndexDesc> indexes = {
milvus::IndexDesc("vector", "vector", milvus::IndexType::AUTOINDEX, milvus::MetricType::COSINE)};
status = client->CreateCollection(milvus::CreateCollectionRequest()
.WithCollectionName("my_collection")
.WithCollectionSchema(schema)
.WithIndexes(std::move(indexes)));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
}
status = client->AlterCollectionProperties(milvus::AlterCollectionPropertiesRequest()
.WithCollectionName("my_collection")
.AddProperty(milvus::COLLECTION_TTL_SECONDS, "1209600"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "YOUR_CLUSTER_ENDPOINT", token: "YOUR_CLUSTER_TOKEN" });
// Assumes "my_collection" was created earlier without TTL.
if (!(await client.hasCollection({ collection_name: "my_collection" })).value) {
await client.createCollection({
collection_name: "my_collection",
fields: [
{ name: "id", data_type: DataType.Int64, is_primary_key: true, autoID: false },
{ name: "vector", data_type: DataType.FloatVector, dim: 128 },
],
index_params: [
{ field_name: "vector", index_type: "AUTOINDEX", metric_type: "COSINE" },
],
});
}
await client.alterCollectionProperties({
collection_name: "my_collection",
properties: { "collection.ttl.seconds": 1209600 },
});
using Milvus.Client.V2.Requests.Collection;
// Assumes "my_collection" was created earlier without TTL
if (await client.HasCollectionAsync(new HasCollectionReq { CollectionName = "my_collection" }) is not { Has: true })
{
await client.CreateCollectionAsync(new CreateCollectionReq
{
CollectionName = "my_collection",
Schema = schema,
Indexes = [new IndexParam("vector", null, IndexType.AutoIndex, MetricType.Cosine)]
});
}
await client.AlterCollectionPropertiesAsync(new AlterCollectionPropertiesReq
{
CollectionName = "my_collection",
Properties = { ["collection.ttl.seconds"] = "1209600" }
});
export schema='{
"autoId": false,
"enableDynamicField": false,
"fields": [
{
"fieldName": "id",
"dataType": "Int64",
"isPrimary": true
},
{
"fieldName": "vector",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": "128"
}
}
]
}'
export indexParams='[
{
"fieldName": "vector",
"metricType": "COSINE",
"indexName": "vector",
"indexType": "AUTOINDEX"
}
]'
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
# Assumes "my_collection" was created earlier without TTL.
if ! curl --silent --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/has" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
\"collectionName\": \"my_collection\"
}" | grep -q '"has":true'; then
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d "{
\"collectionName\": \"my_collection\",
\"schema\": $schema,
\"indexParams\": $indexParams
}"
fi
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/alter_properties" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d "{
\"collectionName\": \"my_collection\",
\"properties\": {
\"collection.ttl.seconds\": \"1209600\"
}
}"
TTL 設定を削除する
コレクション内のデータを無期限に保持する場合は、そのコレクションから TTL 設定を削除するだけです。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
from pymilvus import MilvusClient
client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT", token="YOUR_CLUSTER_TOKEN")
client.drop_collection_properties(
collection_name="my_collection",
property_keys=["collection.ttl.seconds"],
)
import java.util.Collections;
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.collection.request.DropCollectionPropertiesReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
client.dropCollectionProperties(DropCollectionPropertiesReq.builder()
.collectionName("my_collection")
.propertyKeys(Collections.singletonList("collection.ttl.seconds"))
.build());
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/common"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
err = client.DropCollectionProperties(ctx, milvusclient.NewDropCollectionPropertiesOption("my_collection", common.CollectionTTLConfigKey))
if err != nil {
fmt.Println(err.Error())
// handle error
}
use milvus::v2::prelude::*;
let client = ClientV2::new(&ConnectConfig::new()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")).await?;
client.drop_collection_properties(DropCollectionPropertiesRequest::builder()
.collection_name("my_collection")
.property_key("collection.ttl.seconds")
.build()?).await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("YOUR_CLUSTER_ENDPOINT").WithToken("YOUR_CLUSTER_TOKEN"));
status = client->DropCollectionProperties(milvus::DropCollectionPropertiesRequest()
.WithCollectionName("my_collection")
.AddPropertyKey(milvus::COLLECTION_TTL_SECONDS));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "YOUR_CLUSTER_ENDPOINT", token: "YOUR_CLUSTER_TOKEN" });
await client.dropCollectionProperties({
collection_name: "my_collection",
properties: ["collection.ttl.seconds"],
});
using Milvus.Client.V2.Requests.Collection;
await client.DropCollectionPropertiesAsync(new DropCollectionPropertiesReq
{
CollectionName = "my_collection",
DeleteKeys = ["collection.ttl.seconds"]
});
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/drop_properties" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d "{
\"collectionName\": \"my_collection\",
\"propertyKeys\": [
\"collection.ttl.seconds\"
]
}"
エンティティレベルの TTL を設定する
Public Previewエンティティレベルの TTL では、各エンティティが独自の絶対有効期限を持ちます。この時刻は、スキーマで宣言する専用の TIMESTAMPTZ 列に保存され、コレクションの ttl_field プロパティを通じて TTL フィールドとして指定されます。
新しいコレクションで有効にする
作成時にエンティティレベルの TTL を有効にするには、同じ create_collection 呼び出しで 2 つの項目を追加します。スキーマに TIMESTAMPTZ フィールドを追加し、そのフィールドを指す ttl_field プロパティを設定します。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT", token="YOUR_CLUSTER_TOKEN")
schema = client.create_schema(enable_dynamic_field=False)
schema.add_field("id", DataType.INT64, is_primary=True, auto_id=False)
schema.add_field("expire_at", DataType.TIMESTAMPTZ, nullable=True)
schema.add_field("vector", DataType.FLOAT_VECTOR, dim=128)
index_params = client.prepare_index_params()
index_params.add_index(field_name="vector", index_type="AUTOINDEX",
metric_type="COSINE")
client.create_collection(
collection_name="my_collection",
schema=schema,
index_params=index_params,
properties={"ttl_field": "expire_at"},
)
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
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;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
CreateCollectionReq.CollectionSchema schema = CreateCollectionReq.CollectionSchema.builder().build();
schema.addField(AddFieldReq.builder().fieldName("id").dataType(DataType.Int64)
.isPrimaryKey(true).autoID(false).build());
schema.addField(AddFieldReq.builder().fieldName("expire_at").dataType(DataType.Timestamptz)
.isNullable(true).build());
schema.addField(AddFieldReq.builder().fieldName("vector").dataType(DataType.FloatVector)
.dimension(128).build());
IndexParam indexParam = IndexParam.builder().fieldName("vector")
.indexType(IndexParam.IndexType.AUTOINDEX)
.metricType(IndexParam.MetricType.COSINE).build();
Map<String, String> properties = new HashMap<>();
properties.put("ttl_field", "expire_at");
client.createCollection(CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.indexParams(Collections.singletonList(indexParam))
.properties(properties)
.build());
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/entity"
"github.com/milvus-io/milvus/client/v3/index"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
schema := entity.NewSchema().WithDynamicFieldEnabled(false).
WithField(entity.NewField().WithName("id").WithIsAutoID(false).WithDataType(entity.FieldTypeInt64).WithIsPrimaryKey(true)).
WithField(entity.NewField().WithName("expire_at").WithDataType(entity.FieldTypeTimestamptz).WithNullable(true)).
WithField(entity.NewField().WithName("vector").WithDataType(entity.FieldTypeFloatVector).WithDim(128))
indexOptions := []milvusclient.CreateIndexOption{
milvusclient.NewCreateIndexOption("my_collection", "vector", index.NewAutoIndex(entity.COSINE)),
}
err = client.CreateCollection(ctx, milvusclient.NewCreateCollectionOption("my_collection", schema).
WithIndexOptions(indexOptions...).
WithProperty("ttl_field", "expire_at"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
use milvus::v2::prelude::*;
let client = ClientV2::new(&ConnectConfig::new()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")).await?;
let schema = CollectionSchema::new()
.enable_dynamic_field(false)
.add_field(FieldSchema::new().name("id").data_type(DataType::Int64).primary_key(true).auto_id(false))
.add_field(FieldSchema::new().name("expire_at").data_type(DataType::Timestamptz).nullable(true))
.add_field(FieldSchema::new().name("vector").data_type(DataType::FloatVector).dimension(128));
let index_params = vec![
IndexParam::new().field_name("vector").index_type(IndexType::AutoIndex).metric_type(MetricType::Cosine),
];
client.create_collection(CreateCollectionRequest::builder()
.collection_name("my_collection")
.schema(schema)
.index_params(index_params)
.properties(std::collections::HashMap::from([("ttl_field".to_string(), "expire_at".to_string())]))
.build()?).await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("YOUR_CLUSTER_ENDPOINT").WithToken("YOUR_CLUSTER_TOKEN"));
milvus::CollectionSchemaPtr schema = std::make_shared<milvus::CollectionSchema>();
schema->AddField(milvus::FieldSchema("id", milvus::DataType::INT64, "", true, false));
schema->AddField(milvus::FieldSchema("expire_at", milvus::DataType::TIMESTAMPTZ).WithNullable(true));
schema->AddField(milvus::FieldSchema("vector", milvus::DataType::FLOAT_VECTOR).WithDimension(128));
std::vector<milvus::IndexDesc> indexes = {
milvus::IndexDesc("vector", "vector", milvus::IndexType::AUTOINDEX, milvus::MetricType::COSINE)};
status = client->CreateCollection(milvus::CreateCollectionRequest()
.WithCollectionName("my_collection")
.WithCollectionSchema(schema)
.WithIndexes(std::move(indexes))
.AddProperty("ttl_field", "expire_at"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
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",
fields: [
{ name: "id", data_type: DataType.Int64, is_primary_key: true, autoID: false },
{ name: "expire_at", data_type: DataType.Timestamptz, nullable: true },
{ name: "vector", data_type: DataType.FloatVector, dim: 128 },
],
index_params: [
{ field_name: "vector", index_type: "AUTOINDEX", metric_type: "COSINE" },
],
properties: { ttl_field: "expire_at" },
});
using Milvus.Client.V2;
using Milvus.Client.V2.Requests.Collection;
using Milvus.Client.V2.Types;
MilvusClientV2 client = new(new ConnectConfig
{
Uri = "YOUR_CLUSTER_ENDPOINT",
ApiKey = "YOUR_CLUSTER_TOKEN"
});
CollectionSchema schema = new()
{
EnableDynamicFields = false,
Fields =
{
new FieldSchema("id", DataType.Int64, isPrimaryKey: true),
new FieldSchema("expire_at", DataType.Timestamptz) { Nullable = true },
new FieldSchema("vector", DataType.FloatVector) { Dimension = 128 }
}
};
await client.CreateCollectionAsync(new CreateCollectionReq
{
CollectionName = "my_collection",
Schema = schema,
Indexes = [new IndexParam("vector", null, IndexType.AutoIndex, MetricType.Cosine)],
Properties = { ["ttl_field"] = "expire_at" }
});
export schema='{
"autoId": false,
"enableDynamicField": false,
"fields": [
{
"fieldName": "id",
"dataType": "Int64",
"isPrimary": true
},
{
"fieldName": "expire_at",
"dataType": "Timestamptz",
"nullable": true
},
{
"fieldName": "vector",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": "128"
}
}
]
}'
export indexParams='[
{
"fieldName": "vector",
"metricType": "COSINE",
"indexName": "vector",
"indexType": "AUTOINDEX"
}
]'
export params='{
"ttlField": "expire_at"
}'
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d "{
\"collectionName\": \"my_collection\",
\"schema\": $schema,
\"indexParams\": $indexParams,
\"params\": $params
}"
コレクションを作成したら、ISO 8601 のタイムスタンプ文字列を使用してエンティティを挿入します。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
import random
from pymilvus import MilvusClient
client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT", token="YOUR_CLUSTER_TOKEN")
# Assumes "my_collection" was created earlier with `ttl_field`: "expire_at"
rows = [
# Never expires
{"id": 1, "expire_at": None,
"vector": [random.random() for _ in range(128)]},
# Expires at 2026-12-31 UTC midnight
{"id": 2, "expire_at": "2026-12-31T00:00:00Z",
"vector": [random.random() for _ in range(128)]},
# Shanghai local time — normalized to UTC internally
{"id": 3, "expire_at": "2027-01-01T00:00:00+08:00",
"vector": [random.random() for _ in range(128)]},
]
client.insert("my_collection", rows)
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.google.gson.Gson;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.vector.request.InsertReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
// Assumes "my_collection" was created earlier with `ttl_field`: "expire_at".
Gson gson = new Gson();
Random rng = new Random();
List<Float> vector = new ArrayList<>();
for (int i = 0; i < 128; i++) vector.add(rng.nextFloat());
List<JsonObject> rows = new ArrayList<>();
// Never expires
JsonObject r1 = new JsonObject();
r1.addProperty("id", 1);
r1.add("expire_at", JsonNull.INSTANCE);
r1.add("vector", gson.toJsonTree(vector));
rows.add(r1);
// Expires at 2026-12-31 UTC midnight
JsonObject r2 = new JsonObject();
r2.addProperty("id", 2);
r2.addProperty("expire_at", "2026-12-31T00:00:00Z");
r2.add("vector", gson.toJsonTree(vector));
rows.add(r2);
// Shanghai local time — normalized to UTC internally
JsonObject r3 = new JsonObject();
r3.addProperty("id", 3);
r3.addProperty("expire_at", "2027-01-01T00:00:00+08:00");
r3.add("vector", gson.toJsonTree(vector));
rows.add(r3);
client.insert(InsertReq.builder()
.collectionName("my_collection")
.data(rows)
.build());
import (
"context"
"fmt"
"math/rand"
"time"
"github.com/milvus-io/milvus/client/v3/column"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
// Assumes "my_collection" was created earlier with `ttl_field`: "expire_at".
vector1 := make([]float32, 128)
vector2 := make([]float32, 128)
vector3 := make([]float32, 128)
for i := range vector1 {
vector1[i] = rand.Float32()
vector2[i] = rand.Float32()
vector3[i] = rand.Float32()
}
expireAt, err := column.NewNullableColumnTimestamptz("expire_at",
[]time.Time{
{},
time.Date(2026, 12, 31, 0, 0, 0, 0, time.UTC),
time.Date(2027, 1, 1, 0, 0, 0, 0, time.FixedZone("CST", 8*3600)),
},
[]bool{false, true, true})
if err != nil {
fmt.Println(err.Error())
// handle error
}
_, err = client.Insert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection",
column.NewColumnInt64("id", []int64{1, 2, 3}),
expireAt,
column.NewColumnFloatVector("vector", 128, [][]float32{vector1, vector2, vector3}),
))
if err != nil {
fmt.Println(err.Error())
// handle error
}
use milvus::v2::prelude::*;
let client = ClientV2::new(&ConnectConfig::new()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")).await?;
let vector: Vec<f32> = (0..128).map(|_| rand::random::<f32>()).collect();
client.insert(InsertRequest::builder()
.collection_name("my_collection")
.rows(vec![
serde_json::json!({"id": 1, "expire_at": serde_json::Value::Null, "vector": vector.clone()}),
serde_json::json!({"id": 2, "expire_at": "2026-12-31T00:00:00Z", "vector": vector.clone()}),
serde_json::json!({"id": 3, "expire_at": "2027-01-01T00:00:00+08:00", "vector": vector.clone()}),
])
.build()?).await?;
#include <cstdlib>
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("YOUR_CLUSTER_ENDPOINT").WithToken("YOUR_CLUSTER_TOKEN"));
std::vector<float> vector(128);
for (auto& v : vector) {
v = static_cast<float>(rand()) / RAND_MAX;
}
milvus::EntityRows rows;
rows.push_back({{"id", 1}, {"expire_at", nullptr}, {"vector", vector}});
rows.push_back({{"id", 2}, {"expire_at", "2026-12-31T00:00:00Z"}, {"vector", vector}});
rows.push_back({{"id", 3}, {"expire_at", "2027-01-01T00:00:00+08:00"}, {"vector", vector}});
milvus::InsertResponse response;
status = client->Insert(milvus::InsertRequest()
.WithCollectionName("my_collection")
.WithRowsData(std::move(rows)),
response);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "YOUR_CLUSTER_ENDPOINT", token: "YOUR_CLUSTER_TOKEN" });
const vector = Array.from({ length: 128 }, () => Math.random());
// Assumes "my_collection" was created earlier with `ttl_field`: "expire_at".
await client.insert({
collection_name: "my_collection",
data: [
// Never expires
{ id: 1, expire_at: null, vector },
// Expires at 2026-12-31 UTC midnight
{ id: 2, expire_at: "2026-12-31T00:00:00Z", vector },
// Shanghai local time — normalized to UTC internally
{ id: 3, expire_at: "2027-01-01T00:00:00+08:00", vector },
],
});
using Milvus.Client.V2.Requests.Dml;
var vector = Enumerable.Repeat(0.1f, 128).ToArray();
// Assumes "my_collection" was created earlier with `ttl_field`: "expire_at"
await client.InsertAsync(new InsertReq
{
CollectionName = "my_collection",
RowsData =
[
new Dictionary<string, object?> { ["id"] = 1L, ["expire_at"] = null, ["vector"] = vector }, // Never expires
new Dictionary<string, object?> { ["id"] = 2L, ["expire_at"] = "2026-12-31T00:00:00Z", ["vector"] = vector }, // Expires at 2026-12-31 UTC midnight
new Dictionary<string, object?> { ["id"] = 3L, ["expire_at"] = "2027-01-01T00:00:00+08:00", ["vector"] = vector } // Shanghai local time — normalized to UTC internally
]
});
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST --url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/insert" --header "Authorization: Bearer ${TOKEN}" --header "Content-Type: application/json" --header "Request-Timeout: 10" -d "{
\"collectionName\": \"my_collection\",
\"data\": [
{\"id\": 1, \"expire_at\": null, \"vector\": [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]},
{\"id\": 2, \"expire_at\": \"2026-12-31T00:00:00Z\", \"vector\": [0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6]},
{\"id\": 3, \"expire_at\": \"2027-01-01T00:00:00+08:00\", \"vector\": [0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7]}
]
}"
すべてのクエリとベクトル検索で、サーバーは TTL フィルターを自動的に挿入します。フィルターを自分で記述する必要はなく、期限切れのエンティティが結果に表示されることもありません。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
from pymilvus import MilvusClient
client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT", token="YOUR_CLUSTER_TOKEN")
client.load_collection("my_collection")
# Expired rows are filtered out automatically
results = client.query(
collection_name="my_collection",
filter="id >= 0",
output_fields=["id", "expire_at"],
limit=10,
)
print(results)
import java.util.Arrays;
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.collection.request.LoadCollectionReq;
import io.milvus.v2.service.vector.request.QueryReq;
import io.milvus.v2.service.vector.response.QueryResp;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
client.loadCollection(LoadCollectionReq.builder()
.collectionName("my_collection")
.build());
// Expired rows are filtered out automatically
QueryResp results = client.query(QueryReq.builder()
.collectionName("my_collection")
.filter("id >= 0")
.outputFields(Arrays.asList("id", "expire_at"))
.limit(10L)
.build());
System.out.println(results.getQueryResults());
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
_, err = client.LoadCollection(ctx, milvusclient.NewLoadCollectionOption("my_collection"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
// Expired rows are filtered out automatically
resultSet, err := client.Query(ctx, milvusclient.NewQueryOption("my_collection").
WithFilter("id >= 0").
WithOutputFields("id", "expire_at").
WithLimit(10))
if err != nil {
fmt.Println(err.Error())
// handle error
}
fmt.Println(resultSet.GetColumn("id"))
use milvus::v2::prelude::*;
let client = ClientV2::new(&ConnectConfig::new()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")).await?;
client.load_collection(LoadCollectionRequest::builder()
.collection_name("my_collection")
.build()?).await?;
let results = client.query(QueryRequest::builder()
.collection_name("my_collection")
.filter("id >= 0")
.output_fields(["id", "expire_at"])
.limit(10)
.build()?).await?;
println!("{:?}", results);
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("YOUR_CLUSTER_ENDPOINT").WithToken("YOUR_CLUSTER_TOKEN"));
status = client->LoadCollection(milvus::LoadCollectionRequest()
.WithCollectionName("my_collection"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
milvus::QueryResponse response;
status = client->Query(milvus::QueryRequest()
.WithCollectionName("my_collection")
.WithFilter("id >= 0")
.WithOutputFields({"id", "expire_at"})
.WithLimit(10),
response);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
milvus::EntityRows rows;
response.Results().OutputRows(rows);
std::cout << rows.size() << " rows" << std::endl;
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "YOUR_CLUSTER_ENDPOINT", token: "YOUR_CLUSTER_TOKEN" });
await client.loadCollection({ collection_name: "my_collection" });
// Expired rows are filtered out automatically
const results = await client.query({
collection_name: "my_collection",
filter: "id >= 0",
output_fields: ["id", "expire_at"],
limit: 10,
});
console.log(results.data);
using Milvus.Client.V2.Requests.Collection;
using Milvus.Client.V2.Requests.Dql;
using Milvus.Client.V2.Responses.Dql;
using Milvus.Client.V2.Types;
await client.LoadCollectionAsync(new LoadCollectionReq
{
CollectionName = "my_collection"
});
// Expired rows are filtered out automatically
QueryResp results = await client.QueryAsync(new QueryReq
{
CollectionName = "my_collection",
Expression = "id >= 0",
Parameters = new QueryParameters { OutputFields = { "id", "expire_at" }, Limit = 10 }
});
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/load" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d "{
\"collectionName\": \"my_collection\"
}"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/query" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d "{
\"collectionName\": \"my_collection\",
\"filter\": \"id >= 0\",
\"outputFields\": [\"id\", \"expire_at\"],
\"limit\": 10
}"
同じ自動フィルターは client.search() にも適用されます。
Compaction によってエンティティが物理的に削除される前にその有効期間を延長するには、より後の有効期限タイムスタンプ、または None を指定して upsert し、エンティティをクエリ可能なセットに戻します。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
import random
from pymilvus import MilvusClient
client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT", token="YOUR_CLUSTER_TOKEN")
client.upsert("my_collection", [
{"id": 2,
"vector": [random.random() for _ in range(128)],
"expire_at": "2028-01-01T00:00:00Z"},
])
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.vector.request.UpsertReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
Gson gson = new Gson();
Random rng = new Random();
List<Float> vector = new ArrayList<>();
for (int i = 0; i < 128; i++) vector.add(rng.nextFloat());
JsonObject row = new JsonObject();
row.addProperty("id", 2);
row.add("vector", gson.toJsonTree(vector));
row.addProperty("expire_at", "2028-01-01T00:00:00Z");
client.upsert(UpsertReq.builder()
.collectionName("my_collection")
.data(Collections.singletonList(row))
.build());
import (
"context"
"fmt"
"math/rand"
"github.com/milvus-io/milvus/client/v3/column"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
vector := make([]float32, 128)
for i := range vector {
vector[i] = rand.Float32()
}
_, err = client.Upsert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection",
column.NewColumnInt64("id", []int64{2}),
column.NewColumnFloatVector("vector", 128, [][]float32{vector}),
column.NewColumnTimestamptzIsoString("expire_at", []string{"2028-01-01T00:00:00Z"}),
))
if err != nil {
fmt.Println(err.Error())
// handle error
}
use milvus::v2::prelude::*;
let client = ClientV2::new(&ConnectConfig::new()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")).await?;
let vector: Vec<f32> = (0..128).map(|_| rand::random::<f32>()).collect();
client.upsert(UpsertRequest::builder()
.insert(InsertRequest::builder()
.collection_name("my_collection")
.rows(vec![
serde_json::json!({"id": 2, "vector": vector, "expire_at": "2028-01-01T00:00:00Z"}),
])
.build()?)
.build()?).await?;
#include <cstdlib>
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("YOUR_CLUSTER_ENDPOINT").WithToken("YOUR_CLUSTER_TOKEN"));
std::vector<float> vector(128);
for (auto& v : vector) {
v = static_cast<float>(rand()) / RAND_MAX;
}
milvus::EntityRows rows;
rows.push_back({{"id", 2}, {"vector", vector}, {"expire_at", "2028-01-01T00:00:00Z"}});
milvus::UpsertResponse response;
status = client->Upsert(milvus::UpsertRequest()
.WithCollectionName("my_collection")
.WithRowsData(std::move(rows)),
response);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "YOUR_CLUSTER_ENDPOINT", token: "YOUR_CLUSTER_TOKEN" });
const vector = Array.from({ length: 128 }, () => Math.random());
await client.upsert({
collection_name: "my_collection",
data: [
{ id: 2, vector, expire_at: "2028-01-01T00:00:00Z" },
],
});
using Milvus.Client.V2.Requests.Dml;
await client.UpsertAsync(new UpsertReq
{
CollectionName = "my_collection",
RowsData =
[
new Dictionary<string, object?> { ["id"] = 2L, ["vector"] = vector, ["expire_at"] = "2028-01-01T00:00:00Z" }
]
});
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST --url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/upsert" --header "Authorization: Bearer ${TOKEN}" --header "Content-Type: application/json" --header "Request-Timeout: 10" -d "{
\"collectionName\": \"my_collection\",
\"data\": [
{\"id\": 2, \"vector\": [0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8], \"expire_at\": \"2028-01-01T00:00:00Z\"}
]
}"
既存のコレクションで有効にする
コレクションがすでに存在し、collection.ttl.seconds が設定されていない場合は、add_collection_field で TIMESTAMPTZ 列を追加し、alter_collection_properties でその列を TTL フィールドとして指定します。オプションで、履歴行の有効期限タイムスタンプをバックフィルするために upsert を実行できます。バックフィルしない行は NULL のままで、期限切れになりません。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
import random
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT", token="YOUR_CLUSTER_TOKEN")
# Step 1 — add a TIMESTAMPTZ column to the schema
client.add_collection_field(
collection_name="my_collection",
field_name="expire_at",
data_type=DataType.TIMESTAMPTZ,
nullable=True,
)
# Step 2 — mark the new column as the TTL field
client.alter_collection_properties(
collection_name="my_collection",
properties={"ttl_field": "expire_at"},
)
# Step 3 (optional) — backfill expiration timestamps for historical rows
client.upsert("my_collection", [
{"id": 1,
"vector": [random.random() for _ in range(128)],
"expire_at": "2026-12-31T00:00:00Z"},
])
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
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.AddCollectionFieldReq;
import io.milvus.v2.service.collection.request.AlterCollectionPropertiesReq;
import io.milvus.v2.service.vector.request.UpsertReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
// Step 1 — add a TIMESTAMPTZ column to the schema
client.addCollectionField(AddCollectionFieldReq.builder()
.collectionName("my_collection")
.fieldName("expire_at")
.dataType(DataType.Timestamptz)
.isNullable(true)
.build());
// Step 2 — mark the new column as the TTL field
Map<String, String> properties = new HashMap<>();
properties.put("ttl_field", "expire_at");
client.alterCollectionProperties(AlterCollectionPropertiesReq.builder()
.collectionName("my_collection")
.properties(properties)
.build());
// Step 3 (optional) — backfill expiration timestamps for historical rows
Gson gson = new Gson();
Random rng = new Random();
List<Float> vector = new ArrayList<>();
for (int i = 0; i < 128; i++) vector.add(rng.nextFloat());
JsonObject row = new JsonObject();
row.addProperty("id", 1);
row.add("vector", gson.toJsonTree(vector));
row.addProperty("expire_at", "2026-12-31T00:00:00Z");
client.upsert(UpsertReq.builder()
.collectionName("my_collection")
.data(Collections.singletonList(row))
.build());
import (
"context"
"fmt"
"math/rand"
"github.com/milvus-io/milvus/client/v3/column"
"github.com/milvus-io/milvus/client/v3/entity"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
// Step 1 — add a TIMESTAMPTZ column to the schema
err = client.AddCollectionField(ctx, milvusclient.NewAddCollectionFieldOption("my_collection",
entity.NewField().WithName("expire_at").WithDataType(entity.FieldTypeTimestamptz).WithNullable(true)))
if err != nil {
fmt.Println(err.Error())
// handle error
}
// Step 2 — mark the new column as the TTL field
err = client.AlterCollectionProperties(ctx, milvusclient.NewAlterCollectionPropertiesOption("my_collection").
WithProperty("ttl_field", "expire_at"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
// Step 3 (optional) — backfill expiration timestamps for historical rows
vector := make([]float32, 128)
for i := range vector {
vector[i] = rand.Float32()
}
_, err = client.Upsert(ctx, milvusclient.NewColumnBasedInsertOption("my_collection",
column.NewColumnInt64("id", []int64{1}),
column.NewColumnFloatVector("vector", 128, [][]float32{vector}),
column.NewColumnTimestamptzIsoString("expire_at", []string{"2026-12-31T00:00:00Z"}),
))
if err != nil {
fmt.Println(err.Error())
// handle error
}
use milvus::v2::prelude::*;
let client = ClientV2::new(&ConnectConfig::new()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")).await?;
// Step 1 — add a TIMESTAMPTZ column to the schema
client.add_collection_field(AddCollectionFieldRequest::builder()
.collection_name("my_collection")
.field(FieldSchema::new().name("expire_at").data_type(DataType::Timestamptz).nullable(true))
.build()?).await?;
// Step 2 — mark the new column as the TTL field
client.alter_collection_properties(AlterCollectionPropertiesRequest::builder()
.collection_name("my_collection")
.properties(std::collections::HashMap::from([("ttl_field".to_string(), "expire_at".to_string())]))
.build()?).await?;
// Step 3 (optional) — backfill expiration timestamps for historical rows
let vector: Vec<f32> = (0..128).map(|_| rand::random::<f32>()).collect();
client.upsert(UpsertRequest::builder()
.insert(InsertRequest::builder()
.collection_name("my_collection")
.rows(vec![
serde_json::json!({"id": 1, "vector": vector, "expire_at": "2026-12-31T00:00:00Z"}),
])
.build()?)
.build()?).await?;
#include <cstdlib>
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("YOUR_CLUSTER_ENDPOINT").WithToken("YOUR_CLUSTER_TOKEN"));
// Step 1 — add a TIMESTAMPTZ column to the schema
status = client->AddCollectionField(milvus::AddCollectionFieldRequest()
.WithCollectionName("my_collection")
.WithField(std::move(milvus::FieldSchema("expire_at", milvus::DataType::TIMESTAMPTZ).WithNullable(true))));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// Step 2 — mark the new column as the TTL field
status = client->AlterCollectionProperties(milvus::AlterCollectionPropertiesRequest()
.WithCollectionName("my_collection")
.AddProperty("ttl_field", "expire_at"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// Step 3 (optional) — backfill expiration timestamps for historical rows
std::vector<float> vector(128);
for (auto& v : vector) {
v = static_cast<float>(rand()) / RAND_MAX;
}
milvus::EntityRows rows;
rows.push_back({{"id", 1}, {"vector", vector}, {"expire_at", "2026-12-31T00:00:00Z"}});
milvus::UpsertResponse response;
status = client->Upsert(milvus::UpsertRequest()
.WithCollectionName("my_collection")
.WithRowsData(std::move(rows)),
response);
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "YOUR_CLUSTER_ENDPOINT", token: "YOUR_CLUSTER_TOKEN" });
const vector = Array.from({ length: 128 }, () => Math.random());
// Step 1 — add a TIMESTAMPTZ column to the schema
await client.addCollectionField({
collection_name: "my_collection",
field: { name: "expire_at", data_type: DataType.Timestamptz, nullable: true },
});
// Step 2 — mark the new column as the TTL field
await client.alterCollectionProperties({
collection_name: "my_collection",
properties: { ttl_field: "expire_at" },
});
// Step 3 (optional) — backfill expiration timestamps for historical rows
await client.upsert({
collection_name: "my_collection",
data: [
{ id: 1, vector, expire_at: "2026-12-31T00:00:00Z" },
],
});
using Milvus.Client.V2.Requests.Collection;
using Milvus.Client.V2.Types;
// Step 1 — add a TIMESTAMPTZ column to the schema
await client.AddCollectionFieldAsync(new AddCollectionFieldReq
{
CollectionName = "my_collection",
Field = new FieldSchema("expire_at", DataType.Timestamptz) { Nullable = true }
});
// Step 2 — mark the new column as the TTL field
await client.AlterCollectionPropertiesAsync(new AlterCollectionPropertiesReq
{
CollectionName = "my_collection",
Properties = { ["ttl_field"] = "expire_at" }
});
// Step 3 (optional) — backfill expiration timestamps for historical rows
var vector = Enumerable.Repeat(0.1f, 128).ToArray();
await client.UpsertAsync(new UpsertReq
{
CollectionName = "my_collection",
RowsData =
[
new Dictionary<string, object?> { ["id"] = 1L, ["vector"] = vector, ["expire_at"] = "2026-12-31T00:00:00Z" }
]
});
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
# Step 1 — add a TIMESTAMPTZ column to the schema
curl --request POST --url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/fields/add" --header "Authorization: Bearer ${TOKEN}" --header "Content-Type: application/json" --header "Request-Timeout: 10" -d "{
\"collectionName\": \"my_collection\",
\"schema\": {
\"fieldName\": \"expire_at\",
\"dataType\": \"Timestamptz\",
\"nullable\": true
}
}"
# Step 2 — mark the new column as the TTL field
curl --request POST --url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/alter_properties" --header "Authorization: Bearer ${TOKEN}" --header "Content-Type: application/json" --header "Request-Timeout: 10" -d "{
\"collectionName\": \"my_collection\",
\"properties\": {
\"ttl_field\": \"expire_at\"
}
}"
# Step 3 (optional) — backfill expiration timestamps for historical rows
curl --request POST --url "${CLUSTER_ENDPOINT}/v2/vectordb/entities/upsert" --header "Authorization: Bearer ${TOKEN}" --header "Content-Type: application/json" --header "Request-Timeout: 10" -d "{
\"collectionName\": \"my_collection\",
\"data\": [
{\"id\": 1, \"vector\": [0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9], \"expire_at\": \"2026-12-31T00:00:00Z\"}
]
}"
TTL 設定を削除する
エンティティごとの期限切れを停止するには、property_keys で ttl_field を指定して drop_collection_properties を呼び出します。TIMESTAMPTZ 列自体はスキーマに残るため、通常のフィールドとして引き続きクエリできます。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
from pymilvus import MilvusClient
client = MilvusClient(uri="YOUR_CLUSTER_ENDPOINT", token="YOUR_CLUSTER_TOKEN")
client.drop_collection_properties(
collection_name="my_collection",
property_keys=["ttl_field"],
)
import java.util.Collections;
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.collection.request.DropCollectionPropertiesReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
client.dropCollectionProperties(DropCollectionPropertiesReq.builder()
.collectionName("my_collection")
.propertyKeys(Collections.singletonList("ttl_field"))
.build());
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
err = client.DropCollectionProperties(ctx, milvusclient.NewDropCollectionPropertiesOption("my_collection", "ttl_field"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
use milvus::v2::prelude::*;
let client = ClientV2::new(&ConnectConfig::new()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")).await?;
client.drop_collection_properties(DropCollectionPropertiesRequest::builder()
.collection_name("my_collection")
.property_key("ttl_field")
.build()?).await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("YOUR_CLUSTER_ENDPOINT").WithToken("YOUR_CLUSTER_TOKEN"));
status = client->DropCollectionProperties(milvus::DropCollectionPropertiesRequest()
.WithCollectionName("my_collection")
.AddPropertyKey("ttl_field"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "YOUR_CLUSTER_ENDPOINT", token: "YOUR_CLUSTER_TOKEN" });
await client.dropCollectionProperties({
collection_name: "my_collection",
properties: ["ttl_field"],
});
using Milvus.Client.V2.Requests.Collection;
await client.DropCollectionPropertiesAsync(new DropCollectionPropertiesReq
{
CollectionName = "my_collection",
DeleteKeys = ["ttl_field"]
});
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/drop_properties" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d "{
\"collectionName\": \"my_collection\",
\"propertyKeys\": [
\"ttl_field\"
]
}"
ttl_field を削除すると、以降のクエリでは自動フィルターが無効になりますが、すでに期限切れになったエンティティが自動的に再表示されることはありません。以前に期限切れになったエンティティを表示するには、None または将来の有効期限タイムスタンプを指定して upsert してください。これが、同じロードセッション内で期限切れの行へのアクセスを復元する唯一の方法です。
2 つのモード間の移行
2 つの TTL モードは相互に排他的であるため、モードを切り替えるには複数の手順を実行する必要があります。
コレクションレベルの TTL からエンティティレベルの TTL に切り替える
コレクションを collection.ttl.seconds で作成し、エンティティごとの期限切れに切り替える場合は、以下の手順に従ってください。ステップ 1 を省略すると、ステップ 3 は collection TTL is already set, cannot be set ttl field で失敗します。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
import random
from pymilvus import MilvusClient, DataType
client = MilvusClient(
uri="YOUR_CLUSTER_ENDPOINT",
token="YOUR_CLUSTER_TOKEN"
)
# Assumes "my_collection" already exists with `collection.ttl.seconds` set.
# Step 1 — disable collection-level TTL (mandatory; the two modes are mutually exclusive)
client.drop_collection_properties(
collection_name="my_collection",
property_keys=["collection.ttl.seconds"],
)
# Step 2 — add a TIMESTAMPTZ column to the schema
client.add_collection_field(
collection_name="my_collection",
field_name="expire_at",
data_type=DataType.TIMESTAMPTZ,
nullable=True,
)
# Step 3 — set the ttl_field property on the column you just added
client.alter_collection_properties(
collection_name="my_collection",
properties={"ttl_field": "expire_at"},
)
# Step 4 (optional) — backfill expiration timestamps for historical entities
client.upsert("my_collection", [
{"id": 1,
"vector": [random.random() for _ in range(128)],
"expire_at": "2026-12-31T00:00:00Z"},
])
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
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.AddCollectionFieldReq;
import io.milvus.v2.service.collection.request.AlterCollectionPropertiesReq;
import io.milvus.v2.service.collection.request.DropCollectionPropertiesReq;
import io.milvus.v2.service.vector.request.UpsertReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
// Assumes "my_collection" already exists with `collection.ttl.seconds` set.
// Step 1 — disable collection-level TTL (mandatory; the two modes are mutually exclusive)
client.dropCollectionProperties(DropCollectionPropertiesReq.builder()
.collectionName("my_collection")
.propertyKeys(Collections.singletonList("collection.ttl.seconds"))
.build());
// Step 2 — add a TIMESTAMPTZ column to the schema
client.addCollectionField(AddCollectionFieldReq.builder()
.collectionName("my_collection")
.fieldName("expire_at")
.dataType(DataType.Timestamptz)
.isNullable(true)
.build());
// Step 3 — set the ttl_field property on the column you just added
Map<String, String> ttlField = new HashMap<>();
ttlField.put("ttl_field", "expire_at");
client.alterCollectionProperties(AlterCollectionPropertiesReq.builder()
.collectionName("my_collection")
.properties(ttlField)
.build());
// Step 4 (optional) — backfill expiration timestamps for historical entities
Gson gson = new Gson();
Random rng = new Random();
List<Float> vector = new ArrayList<>();
for (int i = 0; i < 128; i++) vector.add(rng.nextFloat());
JsonObject row = new JsonObject();
row.addProperty("id", 1);
row.add("vector", gson.toJsonTree(vector));
row.addProperty("expire_at", "2026-12-31T00:00:00Z");
client.upsert(UpsertReq.builder()
.collectionName("my_collection")
.data(Collections.singletonList(row))
.build());
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/entity"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
// Assumes "my_collection" already exists with `collection.ttl.seconds` set.
// Step 1 — disable collection-level TTL (mandatory; the two modes are mutually exclusive)
err = client.DropCollectionProperties(ctx, milvusclient.NewDropCollectionPropertiesOption("my_collection", "collection.ttl.seconds"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
// Step 2 — add a TIMESTAMPTZ column to the schema
err = client.AddCollectionField(ctx, milvusclient.NewAddCollectionFieldOption("my_collection",
entity.NewField().WithName("expire_at").WithDataType(entity.FieldTypeTimestamptz).WithNullable(true)))
if err != nil {
fmt.Println(err.Error())
// handle error
}
// Step 3 — set the ttl_field property on the column you just added
err = client.AlterCollectionProperties(ctx, milvusclient.NewAlterCollectionPropertiesOption("my_collection").
WithProperty("ttl_field", "expire_at"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
// Step 4 (optional) — backfill expiration timestamps with a column-based upsert.
use milvus::v2::prelude::*;
let client = ClientV2::new(&ConnectConfig::new()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")).await?;
// Assumes "my_collection" already exists with `collection.ttl.seconds` set.
// Step 1 — disable collection-level TTL (mandatory; the two modes are mutually exclusive)
client.drop_collection_properties(DropCollectionPropertiesRequest::builder()
.collection_name("my_collection")
.property_key("collection.ttl.seconds")
.build()?).await?;
// Step 2 — add a TIMESTAMPTZ column to the schema
client.add_collection_field(AddCollectionFieldRequest::builder()
.collection_name("my_collection")
.field(FieldSchema::new().name("expire_at").data_type(DataType::Timestamptz).nullable(true))
.build()?).await?;
// Step 3 — set the ttl_field property on the column you just added
client.alter_collection_properties(AlterCollectionPropertiesRequest::builder()
.collection_name("my_collection")
.properties(std::collections::HashMap::from([("ttl_field".to_string(), "expire_at".to_string())]))
.build()?).await?;
// Step 4 (optional) — backfill expiration timestamps for historical entities
let vector: Vec<f32> = (0..128).map(|_| rand::random::<f32>()).collect();
client.upsert(UpsertRequest::builder()
.insert(InsertRequest::builder()
.collection_name("my_collection")
.rows(vec![
serde_json::json!({"id": 1, "vector": vector, "expire_at": "2026-12-31T00:00:00Z"}),
])
.build()?)
.build()?).await?;
#include <cstdlib>
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("YOUR_CLUSTER_ENDPOINT").WithToken("YOUR_CLUSTER_TOKEN"));
// Assumes "my_collection" already exists with `collection.ttl.seconds` set.
// Step 1 — disable collection-level TTL (mandatory; the two modes are mutually exclusive)
status = client->DropCollectionProperties(milvus::DropCollectionPropertiesRequest()
.WithCollectionName("my_collection")
.AddPropertyKey("collection.ttl.seconds"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// Step 2 — add a TIMESTAMPTZ column to the schema
status = client->AddCollectionField(milvus::AddCollectionFieldRequest()
.WithCollectionName("my_collection")
.WithField(std::move(milvus::FieldSchema("expire_at", milvus::DataType::TIMESTAMPTZ).WithNullable(true))));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
// Step 3 — set the ttl_field property on the column you just added
status = client->AlterCollectionProperties(milvus::AlterCollectionPropertiesRequest()
.WithCollectionName("my_collection")
.AddProperty("ttl_field", "expire_at"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "YOUR_CLUSTER_ENDPOINT", token: "YOUR_CLUSTER_TOKEN" });
// Assumes "my_collection" already exists with `collection.ttl.seconds` set.
// Step 1 — disable collection-level TTL (mandatory; the two modes are mutually exclusive)
await client.dropCollectionProperties({
collection_name: "my_collection",
properties: ["collection.ttl.seconds"],
});
// Step 2 — add a TIMESTAMPTZ column to the schema
await client.addCollectionField({
collection_name: "my_collection",
field: { name: "expire_at", data_type: DataType.Timestamptz, nullable: true },
});
// Step 3 — set the ttl_field property on the column you just added
await client.alterCollectionProperties({
collection_name: "my_collection",
properties: { ttl_field: "expire_at" },
});
using Milvus.Client.V2.Requests.Collection;
using Milvus.Client.V2.Types;
// Assumes "my_collection" already exists with `collection.ttl.seconds` set.
// Step 1 — disable collection-level TTL (mandatory; the two modes are mutually exclusive)
await client.DropCollectionPropertiesAsync(new DropCollectionPropertiesReq
{
CollectionName = "my_collection",
DeleteKeys = ["collection.ttl.seconds"]
});
// Step 2 — add a TIMESTAMPTZ column to the schema
await client.AddCollectionFieldAsync(new AddCollectionFieldReq
{
CollectionName = "my_collection",
Field = new FieldSchema("expire_at", DataType.Timestamptz) { Nullable = true }
});
// Step 3 — set the ttl_field property on the column you just added
await client.AlterCollectionPropertiesAsync(new AlterCollectionPropertiesReq
{
CollectionName = "my_collection",
Properties = { ["ttl_field"] = "expire_at" }
});
// Step 4 (optional) — backfill expiration timestamps for historical entities
var vector = Enumerable.Repeat(0.1f, 128).ToArray();
await client.UpsertAsync(new UpsertReq
{
CollectionName = "my_collection",
RowsData =
[
new Dictionary<string, object?> { ["id"] = 1L, ["vector"] = vector, ["expire_at"] = "2026-12-31T00:00:00Z" }
]
});
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
# Assumes "my_collection" already exists with collection.ttl.seconds set.
# Step 1 — disable collection-level TTL (mandatory; the two modes are mutually exclusive)
curl --request POST --url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/drop_properties" --header "Authorization: Bearer ${TOKEN}" --header "Content-Type: application/json" --header "Request-Timeout: 10" -d "{
\"collectionName\": \"my_collection\",
\"propertyKeys\": [
\"collection.ttl.seconds\"
]
}"
# Step 2 — add a TIMESTAMPTZ column to the schema
curl --request POST --url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/fields/add" --header "Authorization: Bearer ${TOKEN}" --header "Content-Type: application/json" --header "Request-Timeout: 10" -d "{
\"collectionName\": \"my_collection\",
\"schema\": {
\"fieldName\": \"expire_at\",
\"dataType\": \"Timestamptz\",
\"nullable\": true
}
}"
# Step 3 — set the ttl_field property on the column you just added
curl --request POST --url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/alter_properties" --header "Authorization: Bearer ${TOKEN}" --header "Content-Type: application/json" --header "Request-Timeout: 10" -d "{
\"collectionName\": \"my_collection\",
\"properties\": {
\"ttl_field\": \"expire_at\"
}
}"
expire_at をバックフィルしない既存のエンティティは、その列に NULL が入り、期限切れになることはありません。有効期間を有限にする必要がある行のみをバックフィルしてください。
エンティティレベルの TTL からコレクションレベルの TTL に切り替える
逆方向に移行するには、ttl_field を削除して collection.ttl.seconds を設定します。
- Python
- Java
- Go
- Rust
- C++
- NodeJS
- CSharp
- cURL
from pymilvus import MilvusClient
client = MilvusClient(
uri="YOUR_CLUSTER_ENDPOINT",
token="YOUR_CLUSTER_TOKEN"
)
# Assumes "my_collection" already exists with `ttl_field` set.
client.drop_collection_properties(
collection_name="my_collection",
property_keys=["ttl_field"],
)
client.alter_collection_properties(
collection_name="my_collection",
properties={"collection.ttl.seconds": 1209600}, # 14 days
)
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.collection.request.AlterCollectionPropertiesReq;
import io.milvus.v2.service.collection.request.DropCollectionPropertiesReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")
.build());
// Assumes "my_collection" already exists with `ttl_field` set.
client.dropCollectionProperties(DropCollectionPropertiesReq.builder()
.collectionName("my_collection")
.propertyKeys(Collections.singletonList("ttl_field"))
.build());
Map<String, String> properties = new HashMap<>();
properties.put("collection.ttl.seconds", "1209600"); // 14 days
client.alterCollectionProperties(AlterCollectionPropertiesReq.builder()
.collectionName("my_collection")
.properties(properties)
.build());
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v3/common"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "YOUR_CLUSTER_ENDPOINT",
APIKey: "YOUR_CLUSTER_TOKEN",
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
// Assumes "my_collection" already exists with `ttl_field` set.
err = client.DropCollectionProperties(ctx, milvusclient.NewDropCollectionPropertiesOption("my_collection", "ttl_field"))
if err != nil {
fmt.Println(err.Error())
// handle error
}
err = client.AlterCollectionProperties(ctx, milvusclient.NewAlterCollectionPropertiesOption("my_collection").
WithProperty(common.CollectionTTLConfigKey, 1209600)) // 14 days
if err != nil {
fmt.Println(err.Error())
// handle error
}
use milvus::v2::prelude::*;
let client = ClientV2::new(&ConnectConfig::new()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_CLUSTER_TOKEN")).await?;
// Assumes "my_collection" already exists with `ttl_field` set.
client.drop_collection_properties(DropCollectionPropertiesRequest::builder()
.collection_name("my_collection")
.property_key("ttl_field")
.build()?).await?;
client.alter_collection_properties(AlterCollectionPropertiesRequest::builder()
.collection_name("my_collection")
.properties(std::collections::HashMap::from([("collection.ttl.seconds".to_string(), "1209600".to_string())]))
.build()?).await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("YOUR_CLUSTER_ENDPOINT").WithToken("YOUR_CLUSTER_TOKEN"));
// Assumes "my_collection" already exists with `ttl_field` set.
status = client->DropCollectionProperties(milvus::DropCollectionPropertiesRequest()
.WithCollectionName("my_collection")
.AddPropertyKey("ttl_field"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
status = client->AlterCollectionProperties(milvus::AlterCollectionPropertiesRequest()
.WithCollectionName("my_collection")
.AddProperty(milvus::COLLECTION_TTL_SECONDS, "1209600"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "YOUR_CLUSTER_ENDPOINT", token: "YOUR_CLUSTER_TOKEN" });
// Assumes "my_collection" already exists with `ttl_field` set.
await client.dropCollectionProperties({
collection_name: "my_collection",
properties: ["ttl_field"],
});
await client.alterCollectionProperties({
collection_name: "my_collection",
properties: { "collection.ttl.seconds": 1209600 }, // 14 days
});
using Milvus.Client.V2.Requests.Collection;
// Assumes "my_collection" already exists with `ttl_field` set.
await client.DropCollectionPropertiesAsync(new DropCollectionPropertiesReq
{
CollectionName = "my_collection",
DeleteKeys = ["ttl_field"]
});
await client.AlterCollectionPropertiesAsync(new AlterCollectionPropertiesReq
{
CollectionName = "my_collection",
Properties = { ["collection.ttl.seconds"] = "1209600" } // 14 days
});
export CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT"
export TOKEN="YOUR_CLUSTER_TOKEN"
# Assumes "my_collection" already exists with ttl_field set.
curl --request POST --url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/drop_properties" --header "Authorization: Bearer ${TOKEN}" --header "Content-Type: application/json" --header "Request-Timeout: 10" -d "{
\"collectionName\": \"my_collection\",
\"propertyKeys\": [
\"ttl_field\"
]
}"
curl --request POST --url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/alter_properties" --header "Authorization: Bearer ${TOKEN}" --header "Content-Type: application/json" --header "Request-Timeout: 10" -d "{
\"collectionName\": \"my_collection\",
\"properties\": {
\"collection.ttl.seconds\": \"1209600\"
}
}"
FAQ
TTL 設定によりデータはいつ期限切れになりますか?
データは、挿入または upsert された時点に基づいて期限切れになります。期限切れのデータは検索結果に表示されません。詳細については、例 を参照してください。
期限切れのデータはいつ物理的に削除されますか?
データは期限切れになると、検索結果に含まれなくなります。ただし、クラスターの Compaction ポリシーに従い、次のシステム Compaction が実行された後にのみ物理的に削除されます。
期限切れ後すぐにデータを削除する必要がある場合は、お問い合わせください。
CU 容量はいつ減少しますか?
クラスターの CU 容量は、メモリ使用量とストレージ使用量のうち大きい方になります。ストレージ使用量が適用される場合、期限切れのデータが物理的に削除された後、Zilliz Cloud コンソールで CU 容量の減少を確認できます。