Skip to Content
We are live but in Staging 🎉

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:

  1. 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).
  2. 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.
Last updated on