跳转到主要内容
问一次;HeavenBase 决定由谁回答。

1. 构建查询 (Query)

ws.query(Entity) 开始,再添加 filter、向量搜索、投影、排序、分页与执行。
import heavenbase as hb


class Article(hb.Entity):
    title = hb.field(hb.ShortText)
    body = hb.field(hb.LongText)
    tags = hb.field(hb.Array[hb.ShortText]).default([])
    embedding = hb.field(hb.Vector[2])


ws = hb.HeavenBase("core-query", preset="debug")
ws.register(Article)
ws.upsert_many(
    Article,
    [
        {"object_id": "a1", "name": "Agent memory", "title": "Agent memory", "body": "Agents need searchable memory.", "tags": ["agent"], "embedding": [1.0, 0.0]},
        {"object_id": "a2", "name": "Backend plan", "title": "Backend plan", "body": "Backends store physical fields.", "tags": ["storage"], "embedding": [0.0, 1.0]},
    ],
)

frame = (
    ws.query(Article)
    .where(Article.body.match("agent"))
    .near(Article.embedding, [1.0, 0.0], top_k=3)
    .select("title", "score")
    .limit(2)
    .execute()
)

print(frame.rows())
execute() 返回 ResultFrame,而非后端 cursor。

2. 读取 ResultFrame

ResultFrame 即使只投影少量列,也保留 object_id
rows = frame.rows()
print(rows[0]["object_id"])
print(frame.ids)
print(frame.col_names())
这对 Agent 是刻意的:它们可展示紧凑行,之后用同一身份调用 getsetdeletequeryexplain

3. 使用 Filter

字段引用构建类型化 filter 表达式。可用 &|~ 组合。
not_storage = ws.query(Article).where(Article.title != "Backend plan").execute()
tagged = ws.query(Article).where(Article.tags.array_contains("agent")).execute()
combined = ws.query(Article).where((Article.body.match("agent")) & (Article.title != "Draft")).execute()

print(len(not_storage), len(tagged), len(combined))
Agent 或外部客户端需要可序列化查询 spec 时,用 query_json
json_frame = ws.query_json(
    Article,
    {
        "filter": {
            "body": {"$match": "agent"},
            "tags": {"$array_contains": "agent"},
        },
        "select": ["title"],
        "limit": 5,
    },
).execute()

print(json_frame.rows())

4. Mongo 风格 JSON 查询

where() 也接受 Mongo 风格 filter 字典。运算符键使用 $ 前缀,裸值表示 $eq$and$or$not 组合子句。
mongo_frame = (
    ws.query(Article)
    .where(
        {
            "$and": [
                {"body": {"$match": "agent"}},
                {"title": {"$in": ["Agent memory", "Backend plan"]}},
            ]
        }
    )
    .execute()
)

print(mongo_frame.rows())
支持的 $ 运算符映射到已注册的逻辑运算:$eq$ne$lt$lte$gt$gte$in$match$like$ilike$wildcard$regex$contains$array_contains$exists$all。在 Array 字段上,$contains 会自动规范化为 array_contains。同一 filter 形状可作为 query_json spec 的 filter 键使用。

5. 检查 Explain 计划

需要路由诊断时,在执行前调用 explain()
plan = ws.query(Article).where(Article.body.match("agent")).explain()
print(plan["steps"][0]["backend"])
print(plan["steps"][0]["handler_mode"])
计划报告存储放置、所选后端、策略、处理器 (Handler) 种类、处理器 (Handler) 模式,以及回退路径的 unsupported 原因。

6. 在查询外变更行

查询 (Query) 用于读行。写入、更新与删除用 CRUD 方法。
object_id = ws.upsert(
    Article,
    {
        "name": "Query note",
        "title": "Query note",
        "body": "Keep the returned object_id.",
        "tags": ["docs"],
        "embedding": [1.0, 0.0],
    },
)

ws.set(object_id, {"title": "Updated query note"}, entity=Article)
print(ws.get(object_id, entity=Article)["title"])
print(ws.delete((Article, object_id)))
object_id 可能存在于多种实体 (Entity) 类型下时,传入 entity=...

进一步探索

相关资源: