使用 FlexSearch 实现本地全文搜索

搜索功能是网站中提供用户快速查找内容、在不同内容中跳转的一个重要功能,尤其在文档类型网站中几乎是必不可少的常见功能。

实现全文搜索一般都需要将内容存储在数据库中并且由后端提供搜索接口实现。在目前主流的预编译(SSG)静态网站中,通过提前编译时将内容存储为文件格式提供给浏览器实现本地搜索也是另一种常见的方案。

FlexSearch 是一个用于客户端(浏览器、Node.js)和服务器端(Node.js)的高性能全文搜索引擎,主要特点:快速且轻量级、支持多种搜索模式,可以在浏览器和 Node.js 环境中使用。本文介绍如何利用 FlexSearch 实现本地的全文搜索。

使用方式

实现搜索的流程为:

  1. 创建索引
  2. 将数据加入索引
  3. 调用搜索函数根据输入文本执行搜索。

创建索引

FlexSearch 提供了三种不同的索引,按照原文为:

  1. Index is a flat high performance index which stores id-content-pairs.
  2. Worker / WorkerIndex is also a flat index which stores id-content-pairs but runs in background as a dedicated worker thread.
  3. Document is multi-field index which can store complex JSON documents (could also exist of worker indexes).

简单翻译如下:

  1. Index 是一个高性能的平坦索引,用于存储 id-content 对。
  2. Worker / WorkerIndex 也是一个平坦索引,存储 id-content 对,但在后台作为专用的工作线程运行。它适用于需要在独立的线程中执行搜索操作的场景,以提高性能。
  3. Document 是一个多字段索引,可以存储复杂的 JSON 文档,可以包含多个字段和子字段。它也可以由 Worker 索引组成。适用于需要存储和检索多个字段的场景

可以看到这三种索引类型有各自的使用场景,Index 存储的 id-content 对适用于需要快速搜索的场景,如果有性能需求不希望影响页面 UI 渲染可以使用 Worker 索引,如果需要多字段搜索那么 Document 索引会更适合(一般全文搜索也会选用这个方式,因为需要存储多个字段)

Index 索引为例,创建一个索引,只需要新建一个对象即可。

javascript 复制代码
var index = new FlexSearch.Index();

创建索引时也可以配置不同选项,如:

javascript 复制代码
var index = new Index({
    charset: "latin:extra",
    tokenize: "reverse",
    resolution: 9
});

不同参数会有不同的效果,具体需要根据实际需要参考文档配置

将数据加入索引

创建索引后,把需要搜索的数据通过 add 函数加入索引中。注意我们需要为每份数据指定一个 id,最好是数值类型,需要保持唯一。这样后续如果需要更新索引内容时,可以根据 id 直接更新。

javascript 复制代码
index.add(1, "Hello World");
index.add(2, "FlexSearch is awesome");
index.add(3, "Full-text search made easy");

搜索

创建好索引和添加好内容后,执行搜索就十分简单了,只需要执行 search 函数传入搜索文本即可。Index 索引返回的结果是 id 数组。

javascript 复制代码
index.search(query)

如果需要限制搜索数量或者其他搜索选项,可以传入不同的参数

javascript 复制代码
index.search(text, limit);
index.search(text, options);
index.search(text, limit, options);

可以看出,FlexSearchAPI 实现简单易用,主要使用以下几个常见的 API 即可完成搜索功能。

javascript 复制代码
index.add(id, text);
index.search(text);
index.search(text, limit);
index.search(text, options);
index.search(text, limit, options);
index.search(options);
javascript 复制代码
document.add(doc);
document.add(id, doc);
document.search(text);
document.search(text, limit);
document.search(text, options);
document.search(text, limit, options);
document.search(options);
javascript 复制代码
worker.add(id, text);
worker.search(text);
worker.search(text, limit);
worker.search(text, options);
worker.search(text, limit, options);
worker.search(text, limit, options, callback);
worker.search(options);

其他更多 API 可以参考文档

使用 Document 索引实现全文搜索

一般全文搜索会涉及多个字段或者需要存储和获取不同原文档数据的字段和内容,所以使用 Document 索引会更为合适。

Document 索引的实现方式和 Index 索引基本一致,不同的地方在于我们需要指定需要加入到索引的内容字段,如果有多个字段都需要被索引和搜索,那么需要指定多个字段。

创建索引

javascript 复制代码
const index = new Document({
    document: {
        id: "id",
        index: ["content"]
    }
});
javascript 复制代码
var docs = [{
    id: 0,
    title: "Title A",
    content: "Body A"
},{
    id: 1,
    title: "Title B",
    content: "Body B"
}];

const index = new Document({
    document: {
        id: "id",
        index: ["title", "content"]
    }
});

将数据加入索引

javascript 复制代码
index.add({ 
    id: 0, 
    content: "some text"
});

搜索

javascript 复制代码
index.search(query)

默认的返回结果为字段和符合搜索结果的 id 数组

javascript 复制代码
[{
    field: "title",
    result: [0, 1, 2]
},{
    field: "content",
    result: [3, 4, 5]
}]

如果需要返回完整的数据,可以在执行搜索时加上选项 enrich: true

javascript 复制代码
index.search(query, { enrich: true });

返回结果

javascript 复制代码
[{
    field: "title",
    result: [
        { id: 0, doc: { /* document */ }},
        { id: 1, doc: { /* document */ }},
        { id: 2, doc: { /* document */ }}
    ]
},{
    field: "content",
    result: [
        { id: 3, doc: { /* document */ }},
        { id: 4, doc: { /* document */ }},
        { id: 5, doc: { /* document */ }}
    ]
}]

参考链接

相关推荐
web1350858863510 分钟前
前端node.js
前端·node.js·vim
m0_5127446411 分钟前
极客大挑战2024-web-wp(详细)
android·前端
潜意识起点35 分钟前
精通 CSS 阴影效果:从基础到高级应用
前端·css
奋斗吧程序媛40 分钟前
删除VSCode上 origin/分支名,但GitLab上实际上不存在的分支
前端·vscode
IT女孩儿1 小时前
JavaScript--WebAPI查缺补漏(二)
开发语言·前端·javascript·html·ecmascript
m0_748256563 小时前
如何解决前端发送数据到后端为空的问题
前端
请叫我飞哥@3 小时前
HTML5适配手机
前端·html·html5
@解忧杂货铺5 小时前
前端vue如何实现数字框中通过鼠标滚轮上下滚动增减数字
前端·javascript·vue.js
F-2H7 小时前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
gqkmiss7 小时前
Chrome 浏览器插件获取网页 iframe 中的 window 对象
前端·chrome·iframe·postmessage·chrome 插件