Установка TTL коллекции
Milvus может автоматически исключать сущности с помощью политики Time-to-Live (TTL). Просроченные сущности немедленно перестают отображаться в результатах запросов и поиска и физически удаляются из хранилища при следующем цикле уплотнения - обычно в течение 24 часов.
Существует два режима TTL:
TTL на уровне коллекции - одно окно хранения, общее для всех сущностей, задается через свойство
collection.ttl.seconds.TTL на уровне сущности - каждая сущность имеет свое собственное абсолютное время истечения срока хранения в специальном поле
TIMESTAMPTZ, обозначенном как поле TTL через свойствоttl_field.
Эта функция применяется только к управляемым коллекциям.
Ограничения
Два режима TTL являются взаимоисключающими. Для коллекции не могут быть одновременно установлены значения
collection.ttl.secondsиttl_field. Чтобы переключиться, см. раздел Переход между двумя режимами.TTL на уровне коллекции применяет одно окно ко всей коллекции. Если для отдельной строки требуется другое время жизни, используйте TTL на уровне сущности.
Поле для TTL на уровне сущности должно быть
TIMESTAMPTZ. Другие типы отклоняются.Одно поле TTL на коллекцию. Схема может содержать несколько полей
TIMESTAMPTZ, но только одно из них может быть названоttl_field.Удаление
ttl_fieldне восстанавливает просроченные сущности. Чтобы восстановить сущность с истекшим сроком действия, добавьте ее с временной меткойNULLили с будущим сроком действия.
Обзор
Когда использовать TTL
TTL является правильным инструментом, когда сохранение является политикой - вы заранее знаете, что определенные сущности должны со временем исчезнуть, и хотите, чтобы кластер обеспечивал это без написания вами задания cron.
Типичные сценарии:
Наборы данных с временными окнами. Храните только последние N дней журналов, метрик, событий или недолговечных кэшей функций.
Многопользовательские коллекции. Разные арендаторы имеют разные окна хранения в одной коллекции.
Политики хранения на каждую запись. Время жизни каждого документа в конвейерах IoT, хранилищах документов или хранилищах функций MLOps.
Смешение горячих и холодных данных. Короткоживущие сущности сосуществуют с долгосрочными в одной коллекции.
Истечение срока действия в соответствии с требованиями. Минимизация данных в стиле GDPR, когда каждая запись имеет свою собственную дату "удаления до".
Истечение срока годности по факту. Сущность представляет собой запись, которая действительна только до какого-то абсолютного момента (окончание кампании, истечение сессии).
Сущности с истекшим сроком действия не будут отображаться в результатах поиска или запросов. Однако они могут оставаться в хранилище до последующего уплотнения данных, которое должно быть выполнено в течение следующих 24 часов.
Вы можете контролировать время запуска уплотнения данных, установив конфигурационный элемент dataCoord.compaction.expiry.tolerance в конфигурационном файле Milvus.
По умолчанию этот элемент конфигурации имеет значение -1, указывающее на то, что применяется существующий интервал уплотнения данных. Однако если вы измените его значение на целое положительное число, например 12, уплотнение данных будет запускаться через указанное количество часов после истечения срока действия любых сущностей.
Режимы TTL
Эти два режима отвечают на разные вопросы хранения:
TTL на уровне коллекции применяет единый срок хранения к каждой сущности. Срок действия каждой сущности истекает по адресу
insert_ts + ttl_seconds.TTL на уровне сущности позволяет каждой сущности хранить свое абсолютное время истечения срока действия в поле
TIMESTAMPTZ. ЗначениеNULLв этом поле означает, что срок действия сущности не истекает.
Коллекция использует один режим одновременно - оба режима являются взаимоисключающими. Переключение между ними - это многоступенчатая операция; см. раздел Переход между двумя режимами.
Используйте эту таблицу, чтобы выбрать режим:
Если ваша ситуация... |
Используйте |
|---|---|
Каждая сущность в коллекции должна следовать одному и тому же окну хранения |
TTL на уровне коллекции |
Сохранение - это "с момента вставки хранить N секунд". |
TTL на уровне коллекции |
Разные сущности должны иметь разное время жизни в одной коллекции (для арендатора, горячие/холодные, для документа) |
TTL на уровне сущности |
Хранение - это абсолютное время по настенным часам (например, 2027-01-01T00:00:00Z) |
TTL на уровне сущности |
Хранение определяется временной меткой предприятия, а не временной меткой вставки |
TTL на уровне сущности |
Вы хотите обновить или продлить время жизни сущности после вставки |
TTL на уровне сущности |
Некоторые сущности не должны истекать, а другие должны |
TTL на уровне сущности (используйте NULL для бессмертных сущностей) |
Установить TTL на уровне коллекции
Используйте TTL на уровне коллекции, когда все сущности в коллекции должны иметь одинаковый срок хранения.
Включить в новой коллекции
Передайте collection.ttl.seconds (целое число, в секундах) через карту properties во время создания коллекции.
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530")
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("http://localhost:19530")
.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());
const { MilvusClient, DataType } = require("@zilliz/milvus2-sdk-node");
const client = new MilvusClient({ address: "http://localhost:19530" });
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
},
});
err = client.CreateCollection(ctx, milvusclient.NewCreateCollectionOption("my_collection", schema).
WithProperty(common.CollectionTTLConfigKey, 1209600)) // TTL in seconds
if err != nil {
fmt.Println(err.Error())
// handle error
}
export params='{
"ttlSeconds": 1209600
}'
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
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,
\"params\": $params
}"
Включить для существующей коллекции
Вызовите alter_collection_properties с collection.ttl.seconds в карте properties, чтобы применить TTL к коллекции, которая уже используется.
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530")
# 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.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;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.build());
// Assumes "my_collection" was created earlier without TTL.
Map<String, String> properties = new HashMap<>();
properties.put("collection.ttl.seconds", "1209600");
client.alterCollectionProperties(AlterCollectionPropertiesReq.builder()
.collectionName("my_collection")
.properties(properties)
.build());
const { MilvusClient } = require("@zilliz/milvus2-sdk-node");
const client = new MilvusClient({ address: "http://localhost:19530" });
// Assumes "my_collection" was created earlier without TTL.
await client.alterCollectionProperties({
collection_name: "my_collection",
properties: { "collection.ttl.seconds": 1209600 },
});
err = client.AlterCollectionProperties(ctx, milvusclient.NewAlterCollectionPropertiesOption("my_collection").
WithProperty(common.CollectionTTLConfigKey, 60))
if err != nil {
fmt.Println(err.Error())
// handle error
}
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 с этой коллекции.
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
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("http://localhost:19530")
.build());
client.dropCollectionProperties(DropCollectionPropertiesReq.builder()
.collectionName("my_collection")
.propertyKeys(Collections.singletonList("collection.ttl.seconds"))
.build());
const { MilvusClient } = require("@zilliz/milvus2-sdk-node");
const client = new MilvusClient({ address: "http://localhost:19530" });
await client.dropCollectionProperties({
collection_name: "my_collection",
properties: ["collection.ttl.seconds"],
});
err = client.DropCollectionProperties(ctx, milvusclient.NewDropCollectionPropertiesOption("my_collection", common.CollectionTTLConfigKey))
if err != nil {
fmt.Println(err.Error())
// handle error
}
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 на уровне сущностиCompatible with Milvus 3.0.x
TTL на уровне сущности позволяет каждой сущности иметь собственное абсолютное время истечения срока действия. Время хранится в специальном столбце TIMESTAMPTZ, который вы объявляете в схеме, и вы отмечаете этот столбец как поле TTL через свойство коллекции ttl_field.
Включение в новой коллекции
Включение TTL на уровне сущности во время создания коллекции требует двух дополнений в одном вызове create_collection: поле TIMESTAMPTZ в схеме и свойство ttl_field, указывающее на это поле.
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530")
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("http://localhost:19530")
.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());
const { MilvusClient, DataType } = require("@zilliz/milvus2-sdk-node");
const client = new MilvusClient({ address: "http://localhost:19530" });
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" },
});
// go
# restful
Когда коллекция существует, вставьте в нее сущности со строками временных меток ISO 8601.
import random
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
# 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("http://localhost:19530")
.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());
const { MilvusClient } = require("@zilliz/milvus2-sdk-node");
const client = new MilvusClient({ address: "http://localhost:19530" });
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 },
],
});
// go
# restful
При каждом запросе и векторном поиске сервер автоматически вставляет фильтр TTL - вам не придется писать его самостоятельно, и просроченные сущности никогда не появятся в результатах:
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
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("http://localhost:19530")
.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());
const { MilvusClient } = require("@zilliz/milvus2-sdk-node");
const client = new MilvusClient({ address: "http://localhost:19530" });
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);
// go
# restful
Тот же автофильтр применяется к client.search().
Чтобы продлить срок жизни сущности до того, как уплотнение физически удалит ее, сделайте апсерт с более поздней временной меткой истечения срока действия - или None - чтобы вернуть сущность в запрашиваемый набор.
import random
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
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("http://localhost:19530")
.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());
const { MilvusClient } = require("@zilliz/milvus2-sdk-node");
const client = new MilvusClient({ address: "http://localhost:19530" });
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" },
],
});
// go
# restful
Включение в существующую коллекцию
Если коллекция уже существует и в ней не установлен collection.ttl.seconds, добавьте столбец TIMESTAMPTZ с помощью add_collection_field, затем отметьте его как поле TTL с помощью alter_collection_properties. По желанию добавьте исторические строки, чтобы заполнить их временные метки истечения срока действия - строки, которые вы не заполняете, сохраняются на NULL и никогда не истекают.
import random
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530")
# 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("http://localhost:19530")
.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());
const { MilvusClient, DataType } = require("@zilliz/milvus2-sdk-node");
const client = new MilvusClient({ address: "http://localhost:19530" });
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" },
],
});
// go
# restful
Снимите настройку TTL
Вызовите drop_collection_properties с ttl_field в property_keys, чтобы остановить истечение срока действия каждого элемента. Сам столбец TIMESTAMPTZ остается в схеме - вы по-прежнему можете делать к нему запросы как к обычному полю.
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
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("http://localhost:19530")
.build());
client.dropCollectionProperties(DropCollectionPropertiesReq.builder()
.collectionName("my_collection")
.propertyKeys(Collections.singletonList("ttl_field"))
.build());
const { MilvusClient } = require("@zilliz/milvus2-sdk-node");
const client = new MilvusClient({ address: "http://localhost:19530" });
await client.dropCollectionProperties({
collection_name: "my_collection",
properties: ["ttl_field"],
});
// go
# restful
Отмена ttl_field отключает автоматический фильтр для будущих запросов, но сущности, срок действия которых уже истек, не будут автоматически появляться снова. Чтобы сделать ранее просроченную сущность видимой, добавьте ее с временной меткой None или будущим сроком действия - это единственный способ восстановить доступ к просроченным строкам в рамках одной сессии загрузки.
Переход между двумя режимами
Два режима TTL являются взаимоисключающими, поэтому переход между ними состоит из нескольких шагов.
Переход с TTL на уровне коллекции на TTL на уровне сущности
Если ваша коллекция была создана с помощью collection.ttl.seconds и вы хотите перейти на истечение срока действия на уровне сущности, выполните следующие четыре шага. Пропуск шага 1 приведет к тому, что шаг 3 будет провален с collection TTL is already set, cannot be set ttl field.
import random
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530")
# 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("http://localhost:19530")
.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());
// nodejs
// go
# restful
Исторические сущности, для которых вы не заполнили expire_at, будут иметь NULL в этом столбце, что означает, что срок их действия никогда не истечет. Заполняйте только те строки, которые должны иметь ограниченное время жизни.
Переход от TTL на уровне сущности к TTL на уровне коллекции
Чтобы перейти в другом направлении, отбросьте ttl_field и установите collection.ttl.seconds:
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
# 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("http://localhost:19530")
.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());
// nodejs
// go
# restful
Часто задаваемые вопросы
Когда истекает срок действия данных из-за настроек TTL?
В настоящее время срок действия данных зависит от времени, в которое они были вставлены или обновлены. Данные с истекшим сроком действия не будут отображаться в результатах поиска. Подробнее см. в разделе Примеры.
Когда данные с истекшим сроком действия будут физически удалены?
После истечения срока действия данных они не будут отображаться в результатах поиска. Однако физически они будут удалены только после последующего уплотнения системы, в соответствии с политикой уплотнения вашего кластера.