因为现在博客是使用Hugo搭建的静态博客,所以实现搜索相对来说麻烦一点,但是没有搜索总觉的缺少点什么。搜索就看了一下行业内的使用方案,做了一下对比,最终选择MeiliSearch来实现搜索。

主流方式

目前实现方式有很多圈内实现方式也比较多,主要的就是以下几种:

  • 谷歌CSE

    地址:https://cse.google.com

    示例: https://cse.google.com/cse?cx=50f540c36bfafc91f

    创建使用很方便,但是问题也很明显,就是国内的访问问题。

  • Algolia

    地址: https://www.algolia.com/

    行业内很优秀的商业解决方案,开发人员可以使用 API 上传并同步希望搜索的数据,然后可以进行相关的配置,可以使用 InstantSearch 等前端框架进行自定义搜索,为用户创造最佳的搜索体验。

    使用教程:https://jimmysong.io/hugo-handbook/steps/searching-plugin.html

  • 官方提供的其他解决方案

    地址: https://gohugo.io/tools/search/

  • MeiliSearch

    地址: https://www.meilisearch.com/

    这个是使用新兴语言Rust实现的一个搜索引擎,搜索速度快,安装方便。

之所以我这里选择使用MeiliSearch,也是因为一直很关注Rust语言在行业内的使用应用,下载体验MeiliSearch之后,感觉真的很棒,就想运用到自己的博客里面。

实现方式

1.搭建MeiliSearch

搭建的方法有很多种,官方提供了有Curl, Homebrew, Docker, Apt, 源代码,windows等安装方式,具体可以根据实际情况选择安装方式。

具体文档参考: https://docs.meilisearch.com/learn/getting_started/installation.html

我这里使用了Docker的方式,因为我这里是托管到腾讯云的静态网站,所以我也没有实体的机器,就使用了腾讯云的弹性容器服务 EKS,创建了一个0.5核,512M实例,对于我的站点肯定是足够使用了。

EKS地址: https://cloud.tencent.com/product/eks

搭建的时候记得设置MEILI_MASTER_KEY环境变量,原因是设置了Master key之后,系统会为你自动生成一个public key和一个private key。

  • master key可以用来执行所有操作
  • private key可以用来执行除了/keys(用来获取master key和private key)的所有操作。
  • public key只能用来进行搜索操作。

如果你的搜索要对外部开放,一定要设置MEILI_MASTER_KEY环境变量,才能保证你业务的安全。

具体跟keys相关的文档可以参考:https://docs.meilisearch.com/reference/api/keys.html

搭建完成后,还会有一个页面供你来使用体验,比如我的是https://search.wangjunfeng.com/

2. 生成博文索引并上传给MeiliSearch

  • 在你的主题目录themes/xxx/layouts目录下面创建一个index.json文件,内容如下:
1
2
3
4
5
6
7
8
{{- $.Scratch.Add "index" slice -}}
{{- $section := $.Site.GetPage "section" .Section }}
{{- range .Site.AllPages -}}
{{- if and (ne .Type "page") (eq .Kind "page") -}}
{{- $.Scratch.Add "index" (dict "id" .File.UniqueID "type" .Params.Categories "content" (print (substr (.Summary | plainify) 0 20) "...") "summary" (.Summary | plainify)  "hierarchy_lvl0" (index .Params.Categories 0) "hierarchy_lvl1" .Title "hierarchy_lvl2" "" "hierarchy_lvl3" "" "url" .Permalink "tags" .Params.Tags ) }}
{{- end -}}
{{- end -}}
{{- $.Scratch.Get "index" | jsonify -}}

这里参考了漩涡的博客的实现方案。

  • 修改你的站点配置文件config.tomal,在outputs内增加home的json输出。
1
2
[outputs]
home = ["html", "json"]
  • 执行hugo -D就会在public目录下面生成你的博文索引文件index.json

  • 先删除旧索引,如果存在的话,我这里就以blog作为索引的名字。

1
2
3
curl \
  -X DELETE "https://search.wangjunfeng.com/indexes/blog" \
  --header 'X-Meili-API-Key: {PRIVATE_KEY}'
  • 上传博文索引,这里指定了id作为主键。
1
2
3
4
5
curl \
  -X POST 'https://search.wangjunfeng.com/indexes/blog/documents?primaryKey=id' \
  -H "Content-Type: application/json" \
  -H "X-Meili-API-Key: {PRIVATE_KEY}" \
  --data @./public/index.json

3. 搭建站点搜索

这里使用了MeiliSearch官方的docs-searchbar.js组件。

docs-searchbar.js文档: https://github.com/meilisearch/docs-searchbar.js

  • 添加相应的js、css

    这里需要根据你的博客模版进行修改,每个站点使用的模版不太一样,索引需要自己来实现了,这里只是借用官方的demo来展示使用方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
  <head>
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/docs-searchbar.js@1.1.11/dist/cdn/docs-searchbar.min.css"
    />
  </head>

  <body>
    <input type="search" id="search-bar-input" />
    <script src="https://cdn.jsdelivr.net/npm/docs-searchbar.js@1.1.11/dist/cdn/docs-searchbar.min.js"></script>
    <script>
      docsSearchBar({
        hostUrl: "https://search.wangjunfeng.com",
        apiKey: "{PUBLIC_KEY}",
        indexUid: "blog",
        inputSelector: "#search-bar-input",
        debug: true, // Set debug to true if you want to inspect the dropdown
      });
    </script>
  </body>
</html>

参考资料