TRIE
The TRIE index in Milvus organizes VARCHAR field values into a prefix tree (a trie). Each character in a string corresponds to an edge in the tree, and shared prefixes are stored only once. This structure makes exact string lookups and prefix matching fast, without scanning every value in the field.
Use the TRIE index if you frequently run queries with:
Exact equality on string values, such as
category == "books"Prefix filtering, such as
name LIKE "abc%"
Supported data types
VARCHARfields. For details, refer to String Field.
TRIE is supported only on VARCHAR fields. To index a string value inside a JSON field, cast the path to VARCHAR and use the NGRAM index instead.
How it works
Milvus implements TRIE in two phases:
Build index
During ingestion, Milvus reads each value of the indexed field.
The values are inserted into a trie: characters are stored along edges, and each terminal node records the entity IDs that share that string.
The completed tree is persisted as the index.
Accelerate queries
For equality, Milvus walks the tree character by character to reach the node for the exact value and returns its entity IDs.
For a prefix, Milvus walks to the node matching the prefix and collects the entity IDs in its subtree.
Matching entity IDs are passed to the query executor for final result assembly.
For equality and prefix filters, lookup cost is proportional to the string length rather than the number of entities, which keeps these queries fast on large collections.
Create a TRIE index
You can create a TRIE index on a VARCHAR field. No extra parameters are required.
The example below shows how to create a TRIE index on a VARCHAR field:
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
# Assume you have defined a VARCHAR field named "category" in your collection schema
# Prepare index parameters
index_params = client.prepare_index_params()
# Add TRIE index on the "category" field
index_params.add_index(
field_name="category", # Target VARCHAR field
index_type="TRIE", # Index type is TRIE
index_name="category_trie" # Optional, name your index
)
# Create the index on the collection
client.create_index(
collection_name="product_catalog",
index_params=index_params
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.IndexParam;
import io.milvus.v2.service.index.request.CreateIndexReq;
import java.util.Collections;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.build());
client.createIndex(CreateIndexReq.builder()
.collectionName("product_catalog")
.indexParams(Collections.singletonList(IndexParam.builder()
.fieldName("category")
.indexType(IndexParam.IndexType.TRIE)
.indexName("category_trie")
.build()))
.build());
import (
"context"
"log"
"github.com/milvus-io/milvus/client/v3/index"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx := context.Background()
cli, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "http://localhost:19530",
})
if err != nil {
log.Fatal("failed to connect to milvus server: ", err.Error())
}
_, err = cli.CreateIndex(ctx, milvusclient.NewCreateIndexOption("product_catalog", "category", index.NewTrieIndex()).WithIndexName("category_trie"))
if err != nil {
log.Fatal("failed to create index: ", err.Error())
}
use milvus::v2::prelude::*;
let config = ConnectConfig::new().uri("http://localhost:19530");
let client = ClientV2::new(&config).await?;
client
.create_index(
CreateIndexRequest::builder()
.collection_name("product_catalog")
.index_param(
IndexParam::new()
.field_name("category")
.index_type(IndexType::Trie)
.index_name("category_trie"),
)
.build()?,
)
.await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("http://localhost:19530"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
status = client->CreateIndex(milvus::CreateIndexRequest().WithCollectionName("product_catalog")
.AddIndex(milvus::IndexDesc("category", "category_trie", milvus::IndexType::TRIE)));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "http://localhost:19530" });
await client.createIndex({
collection_name: "product_catalog",
field_name: "category",
index_type: "TRIE",
index_name: "category_trie",
});
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d '{
"collectionName": "product_catalog",
"indexParams": [
{
"fieldName": "category",
"indexName": "category_trie",
"indexType": "TRIE"
}
]
}'
# {
# "code": 0,
# "data": {}
# }
Queries accelerated by TRIE
The TRIE index accelerates the following filter patterns on a VARCHAR field:
Equality
filter = 'category == "books"'Membership
filter = 'category in ["books", "electronics"]'Prefix match
filter = 'category LIKE "elec%"'Range
filter = 'category >= "a" and category < "m"'Range evaluation may visit multiple indexed strings.
Suffix, substring, and general LIKE patterns can also be evaluated against the indexed strings, but they may require visiting many distinct values. If your workload is dominated by substring or regex matching, consider the FMINDEX or NGRAM index instead.
Drop an index
Use the drop_index() method to remove an existing index from a collection.
In v2.6.3 or earlier, you must release the collection before dropping a scalar index.
From v2.6.4 or later, you can drop a scalar index directly once it’s no longer needed—no need to release the collection first.
client.drop_index(
collection_name="product_catalog", # Name of the collection
index_name="category_trie" # Name of the index to drop
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.index.request.DropIndexReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.build());
client.dropIndex(DropIndexReq.builder()
.collectionName("product_catalog")
.indexName("category_trie")
.build());
import (
"context"
"log"
"github.com/milvus-io/milvus/client/v3/milvusclient"
)
ctx := context.Background()
cli, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: "http://localhost:19530",
})
if err != nil {
log.Fatal("failed to connect to milvus server: ", err.Error())
}
err = cli.DropIndex(ctx, milvusclient.NewDropIndexOption("product_catalog", "category_trie"))
if err != nil {
log.Fatal("failed to drop index: ", err.Error())
}
use milvus::v2::prelude::*;
let config = ConnectConfig::new().uri("http://localhost:19530");
let client = ClientV2::new(&config).await?;
client
.drop_index(
DropIndexRequest::builder()
.collection_name("product_catalog")
.index_name("category_trie")
.build()?,
)
.await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"
auto client = milvus::MilvusClientV2::Create();
auto status = client->Connect(milvus::ConnectParam("http://localhost:19530"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
status = client->DropIndex(milvus::DropIndexRequest()
.WithCollectionName("product_catalog")
.WithIndexName("category_trie"));
if (!status.IsOk()) {
std::cout << status.Message() << std::endl;
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";
const client = new MilvusClient({ address: "http://localhost:19530" });
await client.dropIndex({
collection_name: "product_catalog",
index_name: "category_trie",
});
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/drop" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d '{
"collectionName": "product_catalog",
"indexName": "category_trie"
}'
# {
# "code": 0,
# "data": {}
# }
Usage notes
Field types: Works with
VARCHARfields only. For more information on data types, refer to String Field.Parameters: No index parameters are needed.
Pattern matching:
TRIEis fastest for equality and prefix filters. Range filters are supported but may visit multiple indexed strings. Suffix, substring, and generalLIKEpatterns can be evaluated but may require scanning many indexed strings.