唯杰地图 logo唯杰地图
VJMAP
EN

全文搜索 (Full-text Search)

vjmap-service/references/api/09-fullsearch.md 6.5 KB211 行
原文

分类代号:C.9 本章共 3 个接口
可关闭特性:config.yaml 里 fullsearch.disable: true 会让这组路由完全不注册;当 full_search 返回 VjmapError(404) 时即判定为"关闭"。

vjmap 内置 bleve 作为 CAD 图纸全文索引,主要用于搜"图上某段文字在哪儿"。典型使用场景:

  • 用户在前端搜索框里输入"消防栓",后端返回所有匹配到的文字 + bbox,前端画框高亮
  • 按图元类型(单行/多行/属性注记/图层名/块名…)过滤
  • 按工作区 / map_ver 隔离

快速索引

序号 SDK 方法 URL
58 full_search / fullSearch POST /api/v1/service/fullsearch/search(也支持 GET)
59 full_search_add / fullSearchAdd POST /api/v1/service/fullsearch/add
60 full_search_delete / fullSearchDelete DELETE /api/v1/service/fullsearch/delete

Document 数据结构

{
  "id":       "unique-id",          // 必填,全库唯一
  "map_ver":  "sys_zp_v1",          // 建议填,便于按图过滤
  "content":  "消防栓",              // 被索引的文本
  "type":     1,                    // 见下方 type 表
  "min_x":    0.0,                  // bbox
  "min_y":    0.0,
  "max_x":    1.0,
  "max_y":    1.0,
  "props":    {...},                // 任意附加属性
  "workspace":"_",                  // ⚠ 见下方坑位:默认工作区要显式写 "_",不能留空
  "data":     "..."                  // 原始业务载荷(由你自己定义)
}

type 常用值

type 说明
1 单行文字
2 多行文本 MText
3 属性注记 Attribute
4 块属性注记
5 图层名
6 块名
7 线型名
8 填充符号名
9 用户自定义

两种调用方式:

  • GET:所有参数走 query,适合简单关键词。
  • POST:所有参数走 JSON body,支持复杂结构(尤其 bounding_box)。

请求字段

字段 类型 说明
query string 搜索关键词
map_ver string 多个用 , 分隔;纯 mapid 自动取最新版本
type string 类型过滤:"1" / "1,2,5" / "1-3" / "1-3,6"
workspace string 工作区,多个逗号分隔;缺省 "_","*" 查全部
limit int 每页条数,默认 10
offset int 分页偏移
fields string 返回字段过滤,逗号分隔
facet bool 是否按 map_ver 聚合 facet
bounding_box string "minx,miny,maxx,maxy" 或 "[..]"
time_range string "2023-01-01~2023-12-31" 或 "7"(最近 N 天)

响应(实采)

{
  "total": 0,
  "hits": [],
  "took": 2
}

total 是命中数量,hits 是文档数组(含 id / content / score / fragments 等 bleve 字段),took 是耗时毫秒。

Python

res = svc.full_search(
    query="消防栓",
    map_ver="proj_v1",
    type_="1,2",
    bounding_box="[0,0,1000,1000]",
    limit=20,
)
for hit in res.get("hits", []):
    print(hit["id"], hit.get("content"))

用 GET 走查询串:

svc.full_search(query="消防栓", limit=5, use_get=True)

Node.js

const res = await svc.fullSearch('消防栓', {
  mapVer: 'proj_v1',
  type: '1,2',
  boundingBox: '[0,0,1000,1000]',
  limit: 20,
});

59 · 新增文档 fullsearch/add

Body

{
  "document": { "id":"...","map_ver":"...","content":"..." }
}

响应(实采)

{
  "id": "nb_fs_1776832372",
  "message": "Document added successfully"
}

坑位:workspace 留空 ≠ 默认工作区。自动同步会把空工作区名归一化为 "_" 再入库,但 fullsearch/add 不做归一化——留空会以 "" 入库;而搜索缺省固定追加 workspace:"_" 的 term 过滤,结果默认搜索永远搜不到。要么 add 时显式传 "workspace":"_",要么搜索时传 workspace:"*"。

Python

svc.full_search_add({
    "id": "firehydrant_01",
    "map_ver": "proj_v1",
    "content": "消防栓",
    "type": 1,
    "workspace": "_",   # 显式写默认工作区,否则搜不到
    "min_x": 100, "min_y": 200, "max_x": 110, "max_y": 210,
})

批量导入:本 SDK 只封装了单条 full_search_add。接口 /fullsearch/batchAdd 用同样的 POST JSON({"documents":[...]});本次不做默认封装,可按需自行 svc._request("POST", svc.service_url("fullsearch/batchAdd"), json_body={"documents":[...]})。


60 · 删除文档 fullsearch/delete

注意是 DELETE 带 JSON body,而不是 ?id=(gin 用 ShouldBindJSON)。

Body

{ "id": "firehydrant_01" }

响应(实采)

{
  "id": "nb_fs_1776832372",
  "message": "Document deleted successfully"
}

Python

svc.full_search_delete("firehydrant_01")

常见错误

HTTP 状态 body 片段 含义
400 "error":"Invalid request parameters" JSON 反序列化失败
400 "error":"Document ID cannot be empty" 未填 id
400 "error":"Invalid bounding box format" bounding_box 解析失败
404 整条路由不存在 fullsearch.disable:true,功能关闭
500 "error":"Failed to initialize service" 后端索引损坏,看服务器日志

使用建议

  1. 用 map_ver 隔离:别把所有图纸的文字都塞一个索引里查全局,会拖慢。
  2. 先 bbox 后全文:多数场景只需搜当前视口,给 bounding_box 可大幅缩小候选集。
  3. 批量构建走后台 job:把"从 DWG 抽文字 → 批量 add"放到离线任务里;前端只做搜索。
  4. 关闭索引也没关系:SDK 的 full_search 会在 404 时抛 VjmapError(404),应用层 catch 一下退化到普通查询即可。
  5. CJK 单字分词:query 走 bleve match query + standard analyzer,中文按单字切分——搜"不存在的词"这类常见汉字组合会命中任何含其中某个字的文档。断言"无结果"请用纯拉丁乱码词;做精确匹配建议配合 map_ver/type/bounding_box 收敛候选集。