Establecer TTL de recogida

Milvus puede caducar entidades automáticamente mediante una política de tiempo de vida (TTL). Las entidades caducadas dejan de aparecer inmediatamente en los resultados de consultas y búsquedas, y se eliminan físicamente del almacenamiento en el siguiente ciclo de compactación, normalmente en 24 horas.

Existen dos modos de TTL:

  • TTL a nivel de colección - una ventana de retención compartida por cada entidad, establecida a través de la propiedad collection.ttl.seconds.

  • TTLa nivel de entidad - cada entidad lleva su propio tiempo de expiración absoluto en un campo dedicado TIMESTAMPTZ, marcado como el campo TTL a través de la propiedad ttl_field.

Esta característica sólo se aplica a las colecciones gestionadas.

Límites

  • Los dos modos TTL son mutuamente excluyentes. Una colección no puede tener tanto collection.ttl.seconds como ttl_field configurados al mismo tiempo. Para cambiar, consulte Migrar entre los dos modos.

  • El TTL a nivel de colección aplica una ventana a toda la colección. Si una sola fila necesita un tiempo de vida diferente, utilice TTL a nivel de entidad.

  • El campo para TTL a nivel de entidad debe ser TIMESTAMPTZ. Se rechazan otros tipos.

  • Un campo TTL por colección. El esquema puede contener varios campos TIMESTAMPTZ, pero sólo uno puede nombrarse en ttl_field.

  • La eliminación de ttl_field no resucita las entidades caducadas. Para restaurar una entidad caducada, vuelva a insertarla con una fecha y hora de caducidad NULL o futura.

Resumen

Ampliar

Cuándo utilizar TTL

TTL es la herramienta correcta cuando la retención es una política - usted sabe de antemano que ciertas entidades deben desaparecer eventualmente, y usted quiere que el cluster lo haga cumplir sin que usted escriba un cron job.

Escenarios típicos:

  • Conjuntos de datos temporales. Conserve sólo los últimos N días de registros, métricas, eventos o cachés de características de corta duración.

  • Colecciones multiusuario. Diferentes inquilinos tienen diferentes ventanas de retención en la misma colección.

  • Políticas de retención por registro. Vida útil por documento en canalizaciones IoT, almacenes de documentos o almacenes de características MLOps.

  • Mezcla de datos fríos y calientes. Las entidades de corta duración coexisten con las de larga duración en la misma colección.

  • Caducidad basada en el cumplimiento. Minimización de datos al estilo GDPR en la que cada registro tiene su propia fecha de caducidad.

  • Caducidad en el tiempo. Una entidad representa un registro que sólo es válido hasta un momento determinado (el final de una campaña o de una sesión).

Las entidades caducadas no aparecerán en ningún resultado de búsqueda o consulta. Sin embargo, pueden permanecer en el almacenamiento hasta la posterior compactación de datos, que debe realizarse en las próximas 24 horas.

Puede controlar cuándo se activa la compactación de datos estableciendo el elemento de configuración dataCoord.compaction.expiry.tolerance en su archivo de configuración de Milvus.

Este elemento de configuración tiene por defecto el valor -1, lo que indica que se aplica el intervalo de compactación de datos existente. Sin embargo, si cambia su valor a un número entero positivo, como 12, la compactación de datos se activará el número de horas especificado después de que caduquen las entidades.

Modos TTL

Los dos modos responden a cuestiones de retención diferentes:

  • TTL a nivel de colección aplica una única duración de retención a cada entidad. Cada entidad caduca en insert_ts + ttl_seconds.

  • TTL a nivel de entidad permite que cada entidad almacene su propia hora de caducidad absoluta en un campo TIMESTAMPTZ. Un NULL en ese campo significa que la entidad nunca expira.

Una colección utiliza un modo a la vez: los dos son mutuamente excluyentes. Pasar de un modo a otro es una operación de varios pasos; consulte Migrar entre los dos modos.

Utilice esta tabla para elegir un modo:

Si su situación es...

Utilice

Cada entidad de la colección debe seguir la misma ventana de retención

TTL a nivel de colección

La retención es "desde el momento de la inserción, mantener N segundos"

TTL a nivel de colección

Diferentes entidades necesitan diferentes tiempos de vida en la misma colección (por inquilino, caliente/frío, por documento)

TTL de entidad

La retención es un tiempo de reloj de pared absoluto (por ejemplo, 2027-01-01T00:00:00Z)

TTL a nivel de entidad

La retención se rige por una marca de tiempo comercial, no por la marca de tiempo de inserción.

TTL a nivel de entidad

Desea actualizar o ampliar el tiempo de vida de una entidad después de la inserción

TTL a nivel de entidad

Algunas entidades no deben caducar nunca, mientras que otras sí

TTL a nivel de entidad (use NULL para las inmortales)

TTL a nivel de colección

Utilice TTL a nivel de colección cuando todas las entidades de la colección deban seguir la misma ventana de retención.

Habilitar en una nueva colección

Pasar collection.ttl.seconds (entero, en segundos) a través del mapa properties en el momento de la creación.

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

Activar en una colección existente

Llamar a alter_collection_properties con collection.ttl.seconds en el mapa properties para aplicar TTL a una colección que ya está en uso.

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

Eliminar la configuración TTL

Si decides mantener los datos en una colección indefinidamente, puedes simplemente eliminar la configuración TTL de esa colección.

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

Establecer TTL a nivel de entidadCompatible with Milvus 3.0.x

El TTL a nivel de entidad permite que cada entidad tenga su propio tiempo de expiración absoluto. El tiempo se almacena en una columna dedicada TIMESTAMPTZ que usted declara en el esquema, y usted marca esa columna como el campo TTL a través de la propiedad de colección ttl_field.

Habilitar en una nueva colección

Habilitar TTL a nivel de entidad en tiempo de creación requiere dos adiciones en la misma llamada create_collection: un campo TIMESTAMPTZ en el esquema, y la propiedad ttl_field apuntando a ese campo.

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

Una vez que la colección existe, inserta entidades con cadenas de fecha y hora 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

En cada consulta y búsqueda vectorial, el servidor auto-inyecta el filtro TTL - usted nunca escribe uno, y las entidades caducadas nunca aparecen en los resultados:

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

El mismo autofiltro se aplica a client.search().

Para extender el tiempo de vida de una entidad antes de que la compactación la elimine físicamente, upsert con una fecha de caducidad posterior - o None - para devolver la entidad al conjunto consultable.

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

Habilitar en una colección existente

Si la colección ya existe y no tiene collection.ttl.seconds establecido, añada una columna TIMESTAMPTZ con add_collection_field, luego márquela como campo TTL con alter_collection_properties. Si lo desea, puede añadir filas históricas para rellenar sus fechas de caducidad; las filas que no rellene se mantendrán en NULL y nunca caducarán.

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

Eliminar la configuración TTL

Llame a drop_collection_properties con ttl_field en property_keys para detener la caducidad por entidad. La columna TIMESTAMPTZ en sí permanece en el esquema - todavía se puede consultar como un campo normal.

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

Al eliminar ttl_field se desactiva el filtro automático para futuras consultas, pero las entidades que ya habían caducado no vuelven a aparecer automáticamente. Para hacer visible una entidad caducada anteriormente, vuelva a insertarla con una marca de tiempo de caducidad None o futura: es la única forma de restaurar el acceso a las filas caducadas dentro de la misma sesión de carga.

Migrar entre los dos modos

Los dos modos TTL son mutuamente excluyentes, por lo que cambiar entre ellos es una operación de varios pasos.

Cambiar de TTL a nivel de colección a TTL a nivel de entidad

Si su colección se creó con collection.ttl.seconds y desea cambiar a la caducidad por entidad, siga estos cuatro pasos. Si omite el paso 1, el paso 3 fallará con 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

Las entidades históricas para las que no rellene expire_at tendrán NULL en esa columna, lo que significa que nunca caducan. Rellena sólo las filas que deben tener un tiempo de vida finito.

Cambiar de TTL a nivel de entidad a TTL a nivel de colección

Para moverse en la otra dirección, elimine ttl_field y establezca 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

Preguntas frecuentes

¿Cuándo caducan los datos debido a la configuración del TTL?

Actualmente, los datos caducan en función del momento en que se insertaron o actualizaron. Los datos caducados no se mostrarán en los resultados de búsqueda. Para más detalles, consulte Ejemplos.

¿Cuándo se eliminarán físicamente los datos caducados?

Una vez que los datos caduquen, no se incluirán en ningún resultado de búsqueda. Sin embargo, sólo se eliminarán físicamente tras la compactación posterior del sistema, de acuerdo con las políticas de compactación de su clúster.