【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除
背景
上篇 blog
【Ubuntu】【Hugo】搭建私人博客:模糊搜索 Fuse.js(二)
分析了模糊搜索的概念,以及 Fuse.js 的核心原理,下面继续
搭建私人博客
OK,接下来继续看 fastsearch.js 的实现

当解析到 JSON 内容后,这里定义了 Fuse.js 的几个核心配置选项,这些选项将决定搜索如何匹配关键词,下面详细说下这里的选项:
keys:定义在哪些字段中搜索 ,这里默认值是['title', 'permalink', 'summary', 'content'],用户输入的关键词会在这几个字段里面匹配threshold:匹配阈值,这里默认值 0.4,范围(0.0 ~ 1.0),其中
0.0 = 完全精确匹配
0.4 = 允许较多错误,比如漏字,顺序错等
1.0 = 任意字符都算匹配(不推荐)distance:模糊匹配半径,默认值 100,需要配合关键词location来使用,表示关键词偏离理想位置多远仍可以接受,不过这里ignoreLocation为 true,那location参数就没啥影响ignoreLocation:是否忽略关键词在文本中的位置,默认值 true
true:全文平等对待,适合博客这样的全文搜索
false:优先匹配开头,适合命令,文件名的搜索方式
这套默认配置很适合博客或者文档站点,因为用户可能记不清完整标题,但关键词还是记得几个的
OK,下面继续看下面的用户自定义配置

前面 blog 说过,import * as params... 表示从 Hugo 构建系统(hugo.toml 配置文件)导入配置参数

这是 Hugo 的 JS 构建管道特性,在模板中,可以把站点配置传入 JS,比如
go
{{ $searchJS := resources.Get "search.js" | js.Build (dict "params" .Site.Params.search) }}
比如 Hugo PaperMod 是在 head.html 模板中传入站点配置的

然后可以在 Hugo 自定义配置文件 hugo.toml 中定义
yaml
params:
search:
fuseOpts:
threshold: 0.3
keys: ["title", "tags"]
另外,这里的 ?? 有点类似 C 语言的三元运算符用法

x: a ?? b 是空值合并运算符,如果 a 是 null 或者 undefined,就用 b 作为 x 的值,这样既允许用户覆盖,又可以保留安全默认值,下面来详细说下里面的自定义选项
isCaseSensitive:表示是否区分大小写,用户没定义的话,默认falseincludeScore:是否在结果中包含匹配分数(调试用),默认falseincludeMathces:是否返回匹配位置(高亮用),默认falseminMatchCharLength:最少输入几个字符才开始搜索,默认 1 个字符就开始搜索shouldSort:是否按匹配度排序结果,默认truefindAllMatches:是否查找所有匹配,而不是只找第一个,默认falsekeys:自定义搜索字段,如果没有自定义的话,默认就是上面提到的['title', 'permalink', 'summary', 'content']location:匹配的起始位置(配合distance选项使用),默认是 0threshold/distance/ignoreLocation:上面提到过了,这里不再赘述
这种设计方式,可以让用户在 hugo.toml 站点的配置文件修改,就能调优搜索体验,而无需修改 JS 代码,很方便
最后,这里再额外补充下 findAllMatches 选项,这里默认 false 不是代表只返回一个搜索结果,这个选项和返回多少文档没有关系,findAllMatches 表示的是在单个字段内,是否查找多个匹配位置,而不是控制返回多少篇文章(搜索结果) ,搜索结果数量由 fuse.search(query, { limit: N }) 决定,与 findAllMatches 无关
举个例子,假设由一篇文章
javascript
{
title: "SSH tunnel and reverse tunnel guide",
content: "Learn how to set up SSH tunnel. Tunnel is powerful."
}
里面有很多 tunnel 关键词,此时用户搜索 tunnel 这个关键词,有两种情况
findAllMatches: false:默认选项,此时Fuse.js在 title 字段中找到第一个tunnel就停止,在content字段中也只记录第一个匹配位置,但整篇文章仍然被作为搜索结果返回(匹配度够高)findAllMatches: true:此时Fuse.js会找出 title 中所有tunnel的位置,同样也会找出 content 中所有匹配的位置,返回的文章数量不变,但每篇文章的matches数组里会有多个匹配项
这个功能主要用于前端高亮显示,如果想把文章中所有匹配词都标红,就把 findAllMatches 设置为 true
OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog
【Ubuntu】【Hugo】搭建私人博客:搜索引擎