Hister 规则四件套速成:skip/priority/versioning/alias 让搜索听你的
Hister 规则四件套速成skip/priority/versioning/alias 让搜索听你的【免费下载链接】histerYour own search engine项目地址: https://gitcode.com/GitHub_Trending/hi/hister自托管搜索引擎最常被问到一个问题索引内容是一回事能不能让搜索结果听我指挥Hister 给出的答案是规则系统——一套以 Go 正则语法为基础、贯穿索引与检索两个阶段的 URL 匹配机制。它解决了私有搜索场景下最真实的痛点索引里混进了广告站和登录墙、重要文档永远排不到前面、跟踪的页面悄悄改版却毫无察觉、常用查询每次都要敲一长串过滤条件。本文基于仓库源码与官方文档拆解 skip、priority、versioning、alias 四类规则的作用域、匹配语法与完整配置流程。读完后你会发现让搜索听你的其实只需要一个rules.json。一个规则系统两个作用阶段理解 Hister 规则的关键是分清它们各自发生在管线的哪一环。四类规则并不是均匀地分布在搜索引擎的各个角落而是被清晰地划分为两组索引阶段写路径skip以及同族的allow在文档进入索引前执行决定这条 URL 值不值得存versioning在文档被重复索引时执行决定这条 URL 的内容变化要不要留档。检索阶段读路径priority在查询执行时对命中文档施加分数加成alias在查询文本进入解析器之前做关键词替换。这个划分在源码里非常直观。规则的类型定义集中在 config/config.gotype Rules struct { Allow *Rule json:allow Skip *Rule json:skip Priority *Rule json:priority Versioning *Rule json:versioning Aliases Aliases json:aliases }每一类规则都以正则模式列表ReStrs的形式存储加载时统一编译。也就是说四类规则共享同一套正则语法区别只在于在哪个时机、对谁生效。skip在写入前把噪音挡在门外skip 规则是最容易上手的URL 一旦匹配任一 skip 模式该文档就会在索引和hister reindex期间被静默丢弃。官方文档给出的典型用例是广告网络、登录页、Cookie 同意弹窗以及任何你永远不想看到的内容见 webui/website/src/content/docs/rules.md^https://ads\.example\.com ^https?://(login|mail)\.example\.com/ .*\?utm_source注意最后一条默认情况下 Hister 只会剥离utm_*查询参数但如果你连带utm_source的整条 URL 都不想要一条规则就能把所有营销追踪链接挡在索引外。skip 与 allow 的组合逻辑在 config/config.go 的IsSkip方法中有精确定义func (r *Rules) IsSkip(s string) bool { if r nil { return false } if r.Allow ! nil len(r.Allow.ReStrs) 0 !r.Allow.Match(s) { return true } return r.Skip ! nil r.Skip.Match(s) }语义是allow 列表非空时URL 必须至少匹配其中一条而 skip 始终拥有更高优先级——你完全可以放行整个站点但排除特定路径。一个值得注意的逃生舱如果某条页面确实被规则误伤浏览器扩展的Index this page now、CLI 的hister index --ignore-rules、或 API 提交时的metadata.ignore_skip_rules: true都能显式覆盖规则并把这个选择随文档一起持久化reindex也不会把它清掉参见 webui/website/src/content/docs/rules.md。而 Web 界面的 Rules 页还提供同时删除已匹配文档的选项让存量文档与规则保持同步。priority把关键来源钉在结果顶部priority 规则解决的是排序问题无论相关性分数如何匹配 priority 模式的文档都会被推到顶部。它的实现是检索阶段的一次分数加成位于 server/indexer/indexer.goconst priorityScoreBoost 100 // boostPriorityURLs scores only candidates from the original query, preserving // its text and ownership filters. func boostPriorityURLs(base query.Query, patterns []string) (query.Query, error) { // 编译所有模式命中 URL 的文档 score priorityScoreBoost }注意priorityScoreBoost 100这个量级——它不是一次微弱的加权而是近乎强制置顶的硬性提升足够把个人 wiki、公司内部文档或你信任的权威源稳定地顶到其他结果前面。代码注释还解释了为什么要用 Go 正则而非 Bleve 自带的语法保持与规则校验一致的匹配语义。典型配置^https://wiki\.example\.com/ ^https://docs\.example\.com/versioning给关注页面装上变更留档versioning 规则的用途是追踪变化URL 匹配 versioning 模式、且内容与上次索引版本不同时Hister 会计算 HTML 与纯文本的 diff match patch 并存入数据库形成可回溯的版本史。这对隐私政策、发布说明、新闻页这类悄悄改版的页面尤其有价值——你可以审计一个可信资源最后变更的时间甚至把每次变更拼成个人 changelog。它的触发点在 server/endpoints.go 的文档提交流程中索引前先取旧文档索引完成后对比新旧内容有差异则调用SaveDocumentVersion存储 diffif d.Type ! document.RemoteFile rules.IsVersioning(d.URL) { existingDoc c.Indexer.GetByURLAndUser(d.URL, d.UserID) } // ...索引完成后... htmlDiff, textDiff : computeDocumentDiff(existingDoc, newDoc) if htmlDiff ! || textDiff ! { model.SaveDocumentVersion(newDoc.URL, newDoc.UserID, htmlDiff, textDiff) }版本查看入口在预览面板一旦某文档积累过至少一次 diff预览区会出现历史版本计数点开后可以按时间浏览每次变更的 diff或重建并展示归档版本。也就是说versioning 不只是一条索引期规则它还顺带点亮了预览区的时光机能力。alias把长查询浓缩成一个词alias 是唯一作用于查询文本本身的规则。在执行搜索之前Hister 会把查询里出现的 alias 关键词替换为其展开形式实现路径在 config/config.gofunc (r *Rules) ResolveAliases(s string) string { sp : strings.Fields(s) changed : false for i, ss : range sp { for k, v : range r.Aliases { if ss k { sp[i] v changed true } } } ... }它按空白分词做精确的整词替换所以你定义的缩写可以被拼进任意查询。官方示例webui/website/src/content/docs/rules.md{ gh: domain:github.com, local: type:file, work: domain:(internal.example.com|jira.example.com) }之后输入work deployment等价于完整查询domain:(internal.example.com|jira.example.com) deployment。日常的高频过滤条件限定域名、限定文件类型、限定站点组从此只需要两个键击。Go 正则语法与 URL 匹配细节allow/skip/priority/versioning 都匹配完整 URL含 scheme、host、path 与查询串并遵循 Go 正则语法。几个关键细节最容易踩坑锚定必须包含 scheme^https://foo.com有效^foo.com无效因为它匹配的是字符串中间位置而非 URL 开头零宽断言look-ahead / look-behind不支持这是 Goregexp的硬限制不是 Hister 的取舍hash 片段在匹配前被剥离https://foo.com/#section会先被规整为https://foo.com/尾部$锚定与查询串互斥/login$匹配不到https://foo.com/login?auth1因为$要求字符串在此处结束而查询串还在后面。所有模式在加载时统一编译非法正则会在LoadRules阶段被拒绝见 config/config.go 的Compile与Rules.Compile避免规则写错导致静默失效。从默认配置到个人化规则一条完整链路规则文件位于单用户模式的数据目录下名为rules.json启用多用户模式后每个用户拥有存在数据库中的私有规则副本。手动编辑、Web 界面 Rules 页、TUI 的规则表单以及 client/rules.go 中封装的/api/rules、/api/add_alias接口都通向同一个结构。一个典型的个人化配置长这样{ skip: [ ^https?://(login|mail)\\.example\\.com/, .*\\?utm_source ], allow: [ ^https://example\\.com/, ^https://docs\\.example\\.org/ ], priority: [ ^https://wiki\\.example\\.com/, ^https://docs\\.example\\.org/ ], versioning: [ ^https://example\\.com/privacy-policy$ ], aliases: { work: domain:(internal.example.com|jira.example.com), local: type:file } }效果是登录页与带营销参数的外链不进索引索引范围被收紧到两个站点的白名单个人 wiki 与内部文档永远排最前隐私政策页每次改版都被留档而每次敲work都会自动展开为整个内部域名组的过滤。这套规则随hister reindex对存量文档生效也可以通过界面一键清理匹配的旧文档。从索引写入前的挡到检索时的顶与换四类规则把搜索引擎最核心的两个自由度——收录什么、如何呈现——完整地交还给了使用者。这恰恰是私有搜索与公共搜索引擎之间最本质的分野前者不是替你决定答案而是让你有能力定义答案。【免费下载链接】histerYour own search engine项目地址: https://gitcode.com/GitHub_Trending/hi/hister创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考