RTREE index
RTREE is a spatial index designed for GEOMETRY fields. If your collection stores geographic or geometric shapes (points, lines, polygons) in WKT (Well‑Known Text) format and you frequently filter by where a shape is (inside, intersects, etc.), RTREE can make those queries much faster.
Typical use cases:
- Geo apps: “Find stores inside this polygon” (delivery zones, service areas)
- Routing / mapping: “Return assets intersecting this road segment”
- Operational analytics: “Show devices within this bounding box”
Note: RTREE requires backend support for GEOMETRY + RTREE (Milvus 2.6.4+).
How RTREE works
RTREE accelerates spatial filtering using a two‑phase approach:
-
Index build (organize shapes)
- For every geometry object, the system computes a Minimum Bounding Rectangle (MBR) — the smallest rectangle that fully contains the object.
- Nearby MBRs are grouped into larger rectangles, forming a tree (leaf nodes → internal nodes → root).
-
Query time (prune + verify)
- The query geometry is also converted into an MBR.
- The tree is traversed from the root and branches whose rectangles do not intersect the query MBR are skipped.
- Only the remaining candidates are checked with the exact spatial predicate (contains / intersects / within, etc.).
This is why RTREE is fast: it avoids scanning every row by quickly discarding geometry that cannot match.
Create an RTREE index
You create RTREE on a GEOMETRY field in your collection schema (for example, a field named geo).
from dodil import Client
from dodil.vbase import VBaseConfig
c = Client(
service_account_id="...",
service_account_secret="...",
)
vbase = c.vbase.connect(
VBaseConfig(
host="vbase-db-<id>.infra.dodil.cloud",
port=443,
scheme="https",
db_name="db_<id>",
)
)
# Create an RTREE index on a GEOMETRY field.
# (The params dict is empty because RTREE does not require extra build parameters.)
vbase.create_index(
collection_name="geo_demo",
field_name="geo",
index_type="RTREE",
index_name="rtree_geo",
params={},
)After creating the index, load the collection (if your workflow requires explicit loading):
vbase.load_collection("geo_demo")Query with spatial filters
RTREE is used automatically when your filter targets the indexed GEOMETRY field.
Example 1: filter-only query
Find shapes fully contained inside a polygon:
filter_expr = "ST_CONTAINS(geo, 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))')"
rows = vbase.query(
collection_name="geo_demo",
filter=filter_expr,
output_fields=["id", "geo"],
limit=10,
)
print(rows)Example 2: vector search + spatial filter
If your collection also has a vector field (for example vec), you can combine semantic similarity with spatial constraints.
query_vec = [[0.1, 0.2, 0.3, 0.4, 0.5]]
filter_expr = "ST_INTERSECTS(geo, 'LINESTRING (1 1, 2 2)')"
hits = vbase.search(
collection_name="geo_demo",
data=query_vec,
limit=5,
filter=filter_expr,
output_fields=["id", "geo"],
)
print(hits)If an RTREE index exists, VBase can prune most candidates before applying the exact spatial predicate.
Drop the index
When you no longer need an index, drop it by name:
vbase.drop_index(
collection_name="geo_demo",
index_name="rtree_geo",
)Practical tips
- WKT input matters: store geometry consistently (same coordinate order and units) so filters behave as expected.
- RTREE is for filters: it speeds up spatial predicates (contains/intersects/within), not vector similarity itself.
- Expect best gains when filters are selective: the more a spatial filter narrows the search area, the bigger the speedup.