1. 路由做什么
路由将每个实体字段映射到一个或多个后端实例与存储策略。单个实体可把标量字段放在一个后端、向量放在另一个、可搜索文本放在第三个,而查询仍从 ws.query(Entity) 开始。
查询时,HeavenBase 为拥有该字段的后端编译每个 filter 或 near 子句,执行受支持的片段,再按 object_id 合并结果帧。
object_id 放置是固定的。HeavenBase 在需要处复制身份,使拆分字段仍能水合成一行逻辑行。
2. 从自动放置开始
工作区 preset 选择实用默认值。在 debug 中,普通行去 main,向量字段可路由到 vec,面向搜索的字段可路由到 search。
import heavenbase as hb
class Document(hb.Entity):
title = hb.field(hb.ShortText)
body = hb.field(hb.LongText)
embedding = hb.field(hb.Vector[2])
ws = hb.HeavenBase("core-routing-auto", preset="debug")
ws.register(Document)
ws.upsert_many(
Document,
[
{"object_id": "d1", "name": "Agent routing", "title": "Agent routing", "body": "Agents query one surface.", "embedding": [1.0, 0.0]},
{"object_id": "d2", "name": "Backend notes", "title": "Backend notes", "body": "Backends store fields.", "embedding": [0.0, 1.0]},
],
)
frame = ws.query(Document).near(Document.embedding, [1.0, 0.0], top_k=1).select("title", "score").execute()
print(frame.rows()[0]["title"])
3. 显式放置字段
字段必须落在特定后端时,使用 .store(to=..., strategy=...)。
class RoutedDocument(hb.Entity):
title = hb.field(hb.ShortText).store(to="main")
body = hb.field(hb.LongText).store(to="main")
embedding = hb.field(hb.Vector[2]).store(to="vec", strategy=hb.VectorIndex)
ws = hb.HeavenBase(
"core-routing-explicit",
backends={
"main": {"type": "inmem"},
"vec": {"type": "inmem"},
},
)
ws.register(RoutedDocument)
routes = (
ws.query(hb.MetaSchema)
.where(hb.MetaSchema.kind == "storage")
.where(hb.MetaSchema.subject_id == "routed-document")
.select("field", "backend", "strategy")
.execute()
.rows()
)
print([(row["field"], row["backend"]) for row in routes])
存储策略是面向后端的提示,例如 InlineColumn、SideTable、VectorIndex、InvertedIndex、JsonField、GraphEdge 与 ExternalRef。多数用户只需显式指定 VectorIndex。
4. 检查查询决策
需要查看查询将使用哪个后端与处理器时,用 explain()。
plan = (
ws.query(RoutedDocument)
.near(RoutedDocument.embedding, [1.0, 0.0], top_k=3)
.explain()
)
print(plan["steps"][0]["backend"])
每一步报告所选后端、存储策略、处理器种类、处理器模式,以及原生路径不可用时的 unsupported 原因。
5. 保持心智模型简单
对应用代码,按此顺序思考:
- 定义实体一次。
- 让 preset 自动路由字段。
- 仅对需要显式放置的字段添加
.store(...)。
- 关心性能或后端选择时用
explain()。
跨后端写入在多后端边界上是尽力而为。部署尚无清晰事务策略前,保持跨后端不变量简单。
进一步探索
相关资源:
- 实体 - 声明类型化字段
- 后端 - 了解后端选择
- 查询 - 执行并解释路由后的查询
- 架构 - 路由背后的系统结构