SiYuan v2.10.0 版本解析:资源文件内容搜索的落地与源码实现

SiYuan v2.10.0 版本解析:资源文件内容搜索的落地与源码实现 SiYuan v2.10.0 版本解析资源文件内容搜索的落地与源码实现【免费下载链接】siyuanAn open-source, privacy-first, self-hosted knowledge workspace where humans and AI agents work together 开源、隐私优先、自托管的知识工作空间让人与智能体在此协作项目地址: https://gitcode.com/GitHub_Trending/si/siyuanSiYuan v2.10.0 是该版本线中的关键节点它首次引入了“资源文件内容搜索”能力使全文搜索从笔记块扩展到.txt、.md、.docx、.xlsx、.pptx等附件文件内部。本篇以 v2.10.0 变更日志 为主体完整梳理该版本的 Feature / Enhancement / Bugfix / Refactor / Development 变更条目并结合当前仓库中 kernel/model/asset_content.go、kernel/sql/asset_content.go、kernel/api/search.go 等源码讲清这一核心功能从“文件解析 → FTS 索引 → 搜索接口”的完整实现链路。版本概览根据官方变更日志v2.10.0 的核心特性是支持搜索资源asset文件的内容初始支持的格式为.txt.md.docx.xlsx.pptx该功能对应上游 issue #8874在当时属于会员付费特性处于早鸟价阶段官方说明见 v2.10.0.md。注意两点适用前提付费限制是当时版本阶段的商业化策略本文聚焦于技术实现本身当前仓库代码中的解析器覆盖面已远超 v2.10.0 发布时的五种格式详见后文阅读源码时应以仓库实际内容为准。核心功能资源内容搜索的源码实现1. 独立的内容索引库与 FTS5 表资源内容搜索没有复用笔记块的 FTS 索引而是使用独立的数据库与虚拟表。从 kernel/sql/database.go 可以看到建表语句CREATE VIRTUAL TABLE asset_contents_fts_case_insensitive USING fts5( id UNINDEXED, name, ext, path, size UNINDEXED, updated UNINDEXED, content, tokenizesiyuan case_insensitive );关键点表名asset_contents_fts_case_insensitive明确表明采用大小写不敏感的 FTS5 索引id、size、updated列标记为UNINDEXED仅存储不参与倒排检索而name、ext、path、content参与分词索引与 kernel/sql/asset_content.go 中的插入语句INSERT INTO asset_contents_fts_case_insensitive (id, name, ext, path, size, updated, content)一一对应tokenizesiyuan case_insensitive是内核自定义的 tokenizer对中文等 CJK 场景做适配保证中英文混合内容的检索效果。2. 解析器体系每种格式一个 ParserNewAssetsSearcher() 注册了完整的扩展名到解析器的映射表。v2.10.0 初始支持的 txt/md/docx/xlsx/pptx 在其中清晰可辨parsers: map[string]AssetParser{ .txt: txtAssetParser, .md: txtAssetParser, .markdown: txtAssetParser, // ... 还有 .json/.log/.sql/.html/.xml/.java/.go/.py/.js/.css/.ts/.sh 等大量源码与文本扩展名 .docx: DocxAssetParser{}, .pptx: PptxAssetParser{}, .xlsx: XlsxAssetParser{}, .pdf: PdfAssetParser{}, .epub: EpubAssetParser{}, },各解析器实现要点均在 kernel/model/asset_content.go解析器实现方式关键约束TxtAssetParser直接读取文件文本超过TxtAssetContentMaxSize4MB跳过非 UTF-8 编码文件不纳入索引utf8.Valid校验见 L543-L564DocxAssetParserdocconv.ConvertDocx转纯文本后归一化仅处理.docx后缀PptxAssetParserdocconv.ConvertPptx转纯文本后归一化仅处理.pptx后缀XlsxAssetParserexcelize.OpenFile遍历所有 Sheet 的每个单元格拼接逐行逐列写入缓冲区PdfAssetParserPDFium WebAssembly 实例池逐页抽取文本移动端不支持util.IsMobileContainer()直接返回页数上限 1024 页PDFAssetContentMaxPage体积上限 128MBPDFAssetContentMaxSize可用环境变量SIYUAN_PDF_ASSET_CONTENT_INDEX_MAX_SIZE覆盖见 L863-L878所有解析前都会经过copyTempAssetL578-L600把资源文件加文件锁后复制到临时目录再解析避免解析过程中文件被并发写入或处于~开头的临时状态。normalizeNonTxtAssetContentL573-L576则用strings.Fields折叠 docx/pptx/xlsx/pdf 转换出的多余空白保证索引文本紧凑。3. 索引写入先删后插 异步队列单文件索引入口 indexAssetContent 的流程是按扩展名取解析器 → 解析内容 →os.Stat取大小与修改时间 → 生成工作空间相对路径形如assets/xxx.docx→ 入队“按路径删除”与“批量插入”两个操作sql.DeleteAssetContentsByPathQueue(p) sql.IndexAssetContentsQueue(assetContents)入队只是追加内存队列见 kernel/sql/queue_asset_content.go真正的落库由定时任务周期性提交kernel/job/cron.go 中go every(util.SQLFlushInterval, sql.FlushAssetContentTxJob)周期性调用 FlushAssetContentQueue。该函数有几个值得注意的工程细节每条操作独立开事务失败时回滚并通过eventbus.Publish(util.EvtSQLAssetContentRebuild)触发全量重建订阅方是 ReindexAssetContent插入采用 512 条一批的批量INSERTinsertAssetContents处理超过 16 条后每 128 条调用一次debug.FreeOSMemory()长事务超过 7 秒会打日志属于典型的批处理内存与耗时治理。此外资源文件被删除时由 removeIndexAssetContent 入队删除操作/api/asset/fullReindexAssetContent路由注册见 kernel/api/router.go提供手动全量重建入口走task.AssetContentDatabaseIndexFull任务队列先sql.InitAssetContentDatabase(true)重置库再全量遍历assets目录FullIndex。4. 搜索 API四种查询方式与分页参数搜索入口POST /api/search/fullTextSearchAssetContent由 fullTextSearchAssetContent 处理参数解析逻辑在 parseSearchAssetContentArgs参数默认值说明page1页码小于 1 时回退为 1pageSize32每页条数小于等于 0 时回退为 32query-查询内容types空按扩展名过滤的布尔映射ext IN (...)method00关键字1查询语法2SQL3正则表达式orderBy00按相关度降序1按相关度升序2按更新时间升序3按更新时间降序method与orderBy到 SQL 的映射在 kernel/model/asset_content.go 与 buildAssetContentOrderBy 中关键字0/查询语法1走 FTS5 的MATCH列过滤固定为{name content}即同时在文件名与正文中匹配见buildAssetContentColumnFilter并用snippet(..., 64)截取 64 字符的上下文片段SQL2直接执行用户语句并通过改写select *为select COUNT(path)统计匹配总数正则3退化为name REGEXP ... OR content REGEXP ...的全表扫描L151-L165性能上弱于 FTS 路径。匹配高亮的处理在 fromSQLAssetContent先EscapeHTML转义再把内核的高亮标记替换为mark//mark前端直接渲染。另有POST /api/search/getAssetContent按索引 ID 取单条支持query/queryMethod高亮与POST /api/search/getAssetContentByPath按assets/xxx相对路径取完整内容原文三者路由均见 kernel/api/router.go。5. 边界与隐私约束源码中有两处与“隐私优先”定位直接相关的边界处理加密笔记本全量索引遍历时通过IsEncryptedAssetPath跳过加密笔记本的 asset密文不能进入搜索索引也避免泄漏文件名集合见 FullIndex 中的注释只读角色发布站点三个搜索接口在只读角色上下文下都会经过model.FilterAssetContentByPublishAccess过滤无权限的资源内容直接置空kernel/api/search.go。本版 Enhancement 条目梳理变更日志列出的增强项逐条如下均保留原始 issue/PR 编号以便溯源列表大纲圆点/编号支持点击放大issue #3502——列表标记区域的交互增强光标与选中块保持一致issue #8918——修复选中块后光标位置不一致的问题粘靠搜索与打开标签页按应用宽度自适应右侧打开issue #8928改进桌面端内核启动检查issue #8929↑/↓ 选择块遇到超级块super block时行为一致issue #8930修复 Enter 后 CtrlZ 光标错位issue #8935改进数据库 URL 列操作PR #8937更新“设置 - 关于 - 版本下载链接”issue #8947平板Pad端支持切换工作空间issue #8948移动端文档树减少缩进issue #8949启用 KaTeX 的 HTML 相关功能PR #8951标题转换为文档时不再以标题名作为文档名issue #8959中文环境下关闭公式警告PR #8963设置 tooltip 最大高度issue #8978新增显示/隐藏 dock 的快捷键配置issue #8979。本版 Bugfix 与 Refactor 条目Bugfix层级标签计数错误issue #8915粘贴的代码块无法自动识别issue #8934表格无法调整居中布局issue #8938插件快捷键设置列表无法折叠PR #8946。Refactor升级 Electronissue #8952。对应地仓库中 app/electron/main.js 与 app/package.json 承载桌面端主进程与 Electron 依赖管理。本版 Development 条目面向插件开发者与集成方的开发侧变更新增插件事件总线open-siyuan-url-plugin与open-siyuan-url-blockPR #8927插件可通过这两个事件响应 siyuan URL 打开插件页/块的请求是插件路由机制的补充修复编辑器中command.fileTreeCallback无法触发的问题issue #8931改进内核 API/api/file/readDir使其返回文件修改时间issue #8945——该改进对插件监听文件变化、按时间排序列目录等场景直接有用。小结v2.10.0 的核心价值在于把 SiYuan 的全文检索边界从“笔记块”推进到“附件文件内容”独立的 FTS5 索引库asset_contents_fts_case_insensitive、按扩展名分派的解析器体系、先删后插的异步索引队列、以及支持关键字/查询语法/SQL/正则四种方式的搜索 APIfullTextSearchAssetContent共同构成了这一能力的技术底座相关实现可分别在 kernel/sql/database.go、kernel/model/asset_content.go、kernel/sql/queue_asset_content.go、kernel/api/search.go 中逐层验证。同时本版本在编辑器光标一致性、移动端/平板端体验、插件事件机制上的大量细节打磨也体现了 SiYuan 在核心功能落地之外对日常使用体验的持续投入。【免费下载链接】siyuanAn open-source, privacy-first, self-hosted knowledge workspace where humans and AI agents work together 开源、隐私优先、自托管的知识工作空间让人与智能体在此协作项目地址: https://gitcode.com/GitHub_Trending/si/siyuan创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考