相关内容
用索引字段计算页面相似度,在模板中输出相关内容列表。
相关内容如何工作
相关内容(related content)依据前置元数据(front matter)中的参数为页面之间计算相似度,用来生成「参见」一类的列表。判定相似度的索引(index)与各自的权重都在站点配置的 related 区段中声明,因此同一套内容可以通过调整配置改变相关结果的取向:更看重共享标签,还是更看重发布时间接近。
列出相关内容
下面这个局部模板列出最多 5 个相关页面,也就是共享 date、keywords 等参数的页面:
{{ with site.RegularPages.Related . | first 5 }}
<p>相关内容:</p>
<ul>
{{ range . }}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
{{ end }}
</ul>
{{ end }}Related 方法只接受一个参数,这个参数可以是 Page,也可以是选项映射。选项映射包含以下选项:
indices:要在哪些索引中搜索。document:为哪个页面查找相关内容,使用选项映射时必填。namedSlices:要搜索的关键词,用keyVals函数构造键值对切片。fragments:用于类型为fragments的索引的关键词列表,会与文档的片段(fragment)标识符匹配。
同时用上全部选项的示例如下:
{{ $page := . }}
{{ $opts := dict
"indices" (slice "tags" "keywords")
"document" $page
"namedSlices" (slice (keyVals "tags" "hugo" "rocks") (keyVals "date" $page.Date))
"fragments" (slice "heading-1" "heading-2")
}}为内容标题建立索引
在 related 配置中加入一个类型为 fragments 的索引,Hugo 就会为正文标题建立索引并据此查找相关内容:
[related]
threshold = 20
includeNewer = true
toLower = false
[[related.indices]]
name = "fragmentrefs"
type = "fragments"
applyFilter = true
weight = 80name 对应一个可选的前置元数据切片参数,用于从页面层链接到片段或标题层。开启 applyFilter 后,结果中每个页面的 .HeadingsFiltered 会给出过滤后的标题,便于在相关列表里显示到标题一级:
{{ $related := site.RegularPages.Related . | first 5 }}
{{ with $related }}
<h2>参见</h2>
<ul>
{{ range $i, $p := . }}
<li>
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
{{ with .HeadingsFiltered }}
<ul>
{{ range . }}
{{ $link := printf "%s#%s" $p.RelPermalink .ID | safeURL }}
<li><a href="{{ $link }}">{{ .Title }}</a></li>
{{ end }}
</ul>
{{ end }}
</li>
{{ end }}
</ul>
{{ end }}默认配置
[related]
threshold = 80
includeNewer = false
toLower = false
[[related.indices]]
name = "keywords"
weight = 100
[[related.indices]]
name = "date"
weight = 10
[[related.indices]]
name = "tags"
weight = 80顶层设置
| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
threshold |
int | 80 |
取值范围 [0, 100],越低匹配越多,但相关性可能越弱 |
includeNewer |
bool | false |
是否把发布日期晚于当前页面的内容纳入结果 |
toLower |
bool | false |
是否把索引与查询中的关键词统一转为小写,结果更准但略有性能开销 |
按索引的设置
| 键 | 类型 | 默认值 | 说明 |
|---|---|---|---|
name |
string | — | 索引名,直接对应页面参数,支持字符串、列表以及时间日期对象 |
weight |
int | 0 |
该索引相对其他索引的重要性;为 0 相当于关闭该索引,也可以为负 |
type |
string | basic |
取 basic 或 fragments |
pattern |
string | 日期索引为 2006 |
仅对日期有意义,如 200601 表示按年月加权 |
applyFilter |
bool | false |
是否对搜索结果应用类型专属过滤,仅用于 fragments |
cardinalityThreshold |
int | 0 |
取值范围 [1, 100],出现频率高于该百分比的索引值会被移出索引,0 表示不过滤 |
minTokenLength |
int | 0 |
开启 tokenize 时按 Unicode 码点计算的最短词长,0 表示不限制 |
tokenize |
bool | false |
是否先按空白把字符串值切成词再建立索引 |
toLower |
bool | false |
索引级的同名词,含义与顶层设置一致 |
tokenize 只按空白切分,因此 apple 与 apples 会被当作两个不同的词,中文、日文等不以空格分词的语言不受支持。分词会让索引体积随词数增长,可配合 minTokenLength 排除短词、用 cardinalityThreshold 移除高频词;minTokenLength 先于 cardinalityThreshold 生效,被排除的词不会进入索引。
示例:按分类法术语关联
设想一个书评站点,用 genres 与 authors 两个分类法(taxonomy)标识每篇书评,希望共享作者或类型的书评互相推荐:
[taxonomies]
author = "authors"
genre = "genres"
[related]
includeNewer = true
threshold = 80
toLower = true
[[related.indices]]
name = "authors"
weight = 2
[[related.indices]]
name = "genres"
weight = 1authors 的权重是 2、genres 是 1,也就是说共享作者的份量是共享类型的两倍。渲染时仍然使用前面那个局部模板。
示例:按标题词关联
若希望标题中含有相同词语的文章互相关联,例如标题里的 Hugo、image、processing 都参与匹配:
[related]
threshold = 50
toLower = true
[[related.indices]]
name = "title"
weight = 1
tokenize = true
minTokenLength = 4tokenize 为 true 时,Hugo 按空白切分标题并逐词建立索引;minTokenLength = 4 会排除 and、the、for 这类短词。