往期推文全新看点(文中附带全新鸿蒙5.0全栈学习笔录)

✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?

✏️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~

✏️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?

✏️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?

✏️ 市场巨变,移动开发行业即将迎来“第二春”?

✏️ 记录一场鸿蒙开发岗位面试经历~

✏️ 持续更新中……


简介

Fuse.js是一款轻量级的JavaScript模糊搜索库,提供了模糊搜索和搜索排序功能。

该库有着如下移植价值:

  • 高性能:Fuse.js使用了一种称为近似字符串匹配的算法,这使得它在大型数据集中的搜索速度非常快。
  • 简单易用:Fuse.js提供了简单易用的API,使得开发者能够轻松地将模糊搜索和搜索排序功能集成到他们的应用程序中。
  • 高度可配置:Fuse.js提供了许多可配置选项,使得开发者能够自定义搜索算法的行为和搜索结果的排序方式。
  • 支持多种数据类型:Fuse.js可以用于不同类型的数据,包括字符串、数字、日期等。
  • 支持多语言搜索:Fuse.js可以处理不同语言的搜索,包括中文、日文、阿拉伯文等。
  • 该库可以用于各种应用场景,例如搜索引擎、电子商务网站、数据可视化等等。

本项目将该库在移植到OpenHarmony上运行,并通过XTS测试。

效果展示

使用该库实现的Demo应用效果如下:

<div align=center>
<img src="./screenshot/fusejs.gif" width="50%" />
</div>

下载安装

ohpm install @isrc/fuse.js

使用说明

字符串列表搜索典型使用示例如下:

// 创建一个包含书籍信息的列表数组,作为待搜索的数据
var list = [
  {
    "title": "Old Man's War",
    "author": "John Scalzi",
    "tags": ["fiction"]
  },
  {
    "title": "The Lock Artist",
    "author": "Steve",
    "tags": ["thriller"]
  }
]

// 配置搜索选项,包括启用分数计算和指定搜索的键(作者和标签)
var options = {
  includeScore: true,
  // 在 'author' 和 'tags' 数组中进行搜索
  keys: ['author', 'tags']
}

// 创建一个 Fuse 搜索实例,将列表和选项传递给它
var fuse = new Fuse(list, options)

// 使用 Fuse 搜索实例执行搜索,查找包含 'tion' 的结果
var result = fuse.search('tion')

此时result变量内容为:

[
  {
    "item": {
      "title": "Old Man's War",
      "author": "John Scalzi",
      "tags": ["fiction"]
    },
    "refIndex": 0,
    "score": 0.03
  }
]

接口说明

方法

search

搜索整个文档集合,并返回搜索结果列表。

fuse.search(/* pattern , options*/)

选项:

  • limitnumber类型):表示返回搜索结果的最大数量。
setCollection

替换整个文档集合。如果未提供索引,则会自动生成一个。示例:

const fruits = ['apple', 'orange']
const fuse = new Fuse(fruits)

fuse.setCollection(['banana', 'pear'])
add

将文档添加到集合中。示例:

const fruits = ['apple', 'orange']
const fuse = new Fuse(fruits)

fuse.add('banana')

console.log(fruits.length)
// => 3
remove

从列表中删除谓词返回true的所有文档,并返回被删除文档的数组。使用两个参数调用谓词:(doc, index)。示例:

const fruits = ['apple', 'orange', 'banana', 'pear']
const fuse = new Fuse(fruits)

const results = fuse.remove((doc) => {
  return doc === 'banana' || doc === 'pear'
})

console.log(fruits.length)
// => 2

console.log(results)
// => ['banana', 'pear']
removeAt

删除指定索引处的文档。示例:

const fruits = ['apple', 'orange', 'banana', 'pear']
const fuse = new Fuse(fruits)

fuse.removeAt(1)

console.log(fruits)
// => ['apple', 'banana', 'pear']
getIndex

返回生成的 Fuse 索引。示例:

const fruits = ['apple', 'orange', 'banana', 'pear']
const fuse = new Fuse(fruits)

console.log(fuse.getIndex().size())
// => 4

配置选项

名称类型默认说明
基本选项
isCaseSensitivebooleanfalse指示比较是否应区分大小写。
includeScorebooleanfalse是否将分数包含在结果集中。分数0表示完全匹配,分数1表示完全不匹配。
includeMatchesbooleanfalse是否应将匹配项包括在结果集中。当设置为true时,结果集中的每个记录都将包括匹配字符的索引。这些索引可以用于高亮显示等目的。
minMatchCharLengthnumber1只有长度超过此值的匹配项才会被返回。(例如,如果要在结果中忽略单个字符的匹配项,请将其设置为2)。
shouldSortbooleantrue是否应对结果列表按分数进行排序。
findAllMatchesbooleanfalse当设置为true时,匹配函数将继续查找搜索模式的末尾,即使在字符串中已经找到完全匹配项。
keysArray[]将被搜索的键的列表。这支持嵌套路径、加权搜索以及在字符串和对象数组中进行搜索。
模糊匹配选项
locationnumber0确定模式大致应在文本中的哪个位置找到。
thresholdnumber0.6匹配算法在什么时候放弃。阈值0.0表示需要完美匹配(字母和位置),阈值1.0会匹配任何内容。
distancenumber100确定匹配与模糊位置(由 location 指定)之间的接近程度。距离模糊位置 distance 个字符的确切字母匹配将得分为完全不匹配。当 distance0 时,要求匹配必须位于精确的 location 所指定的位置。而当 distance1000 时,要求使用 threshold 值为 0.8 进行查找时,完全匹配必须在距离 location 不超过 800 个字符的范围内才能找到。
ignoreLocationbooleanfalsetrue时,搜索将忽略locationdistance,因此模式出现在字符串中的位置并不重要。
高级选项
useExtendedSearchbooleanfalse当为true时,它允许使用类 UNIX 搜索命令。
getFnFunction(obj: T, path: string | string[]) => string | string[]用于获取提供路径的对象值的函数。默认情况下,还将搜索嵌套路径。
sortFnFunction(a, b) => number用于对所有结果进行排序的函数。默认情况下,将按升序相关性得分和升序索引进行排序。
ignoreFieldNormbooleanfalse当为true时,用于排序的相关性得分计算将忽略字段长度规范。
fieldNormWeightnumber1确定字段长度范数对评分的影响程度。值为0等同于忽略字段长度范数。值0.5将大大降低字段长度规范的影响,而值2.0会大大增加其影响。

索引

Fuse.createIndex

预先生成索引列表,然后将其直接传递到 Fuse 实例中。如果列表很大,这将加快实例化速度。示例:

var books = [
  {
    "title": "Old Man's War",
    "author": {
      "firstName": "John",
      "lastName": "Scalzi"
    }
  },
  {
    "title": "The Lock Artist",
    "author": {
      "firstName": "Steve",
      "lastName": "Hamilton"
    }
  }
  /*...*/
]
const options = { keys: ['title', 'author.firstName'] }

// 创建 Fuse 索引
const myIndex = Fuse.createIndex(options.keys, books)
// 使用索引初始化 Fuse
const fuse = new Fuse(books, options, myIndex)

如果在实例化期间未提供索引表,Fuse 将自动索引表。

Fuse.parseIndex

解析序列化的 Fuse 索引。示例:

// (1) 在构建步骤中
// 创建 Fuse 索引
const myIndex = Fuse.createIndex(['title', 'author.firstName'], books)
// 序列化并保存它
fs.writeFile('fuse-index.json', JSON.stringify(myIndex.toJSON()))

// (2) 当应用程序启动时
// 加载和反序列化索引
const fuseIndex = await require('fuse-index.json')
const myIndex = Fuse.parseIndex(fuseIndex)
// 使用索引初始化 Fuse
const fuse = new Fuse(books, options, myIndex)

逻辑查询运算符

Fuse.js 支持逻辑查询操作符。这些操作符用于筛选数据并根据给定条件获取精确的结果。以下表格包含逻辑查询操作符:

名称描述
$and返回与所有子句的条件匹配的所有文档。
$or返回与任何子句的条件匹配的所有文档。
$and
{ $and: [ { <expression_1> }, { <expression_2> } , ... , { <expression_N> } ] }

$and 操作符在表达式数组上执行逻辑 AND 操作,并选择满足所有表达式的条目。$and 操作符使用短路评估(即,如果第一个表达式评估为 false,则 Fuse.js 不会评估剩余的表达式)。

当指定逗号分隔的表达式列表时,Fuse.js 提供了隐式的 AND 操作。在多个表达式中需要指定相同的字段或操作符时,使用 $and 操作符进行显式的 AND 操作是必要的。

示例:

const result = fuse.search({
  $and: [{ author: 'abc' }, { title: 'xyz' }]
})
$or

$or 操作符在表达式数组上执行逻辑 OR 操作,并选择满足至少一个表达式的条目。$or 操作符使用短路评估(即,如果第一个表达式评估为 true,则 Fuse.js 不会评估剩余的表达式)。

示例:

const result = fuse.search({
  $or: [{ author: 'abc' }, { author: 'def' }]
})
具有点分隔键的逻辑搜索

要处理包含点的键,可以在构建查询时使用 $path$val 属性。示例:

[
  {
    "title": "Old Man's War",
    "author": {
      "first.name": "John",
      "last.name": "Scalzi",
      "age": "61"
    }
  }
]

const options = {
  useExtendedSearch: true,
  includeScore: true,
  keys: [
    'title',
    ['author', 'first.name'],
    ['author', 'last.name'],
    'author.age'
  ]
}

const query = {
  $and: [
    {
      $path: ['author', 'first.name'],
      $val: 'jon'
    },
    {
      $path: ['author', 'last.name'],
      $val: 'scazi'
    }
  ]
}
与扩展搜索一起使用

逻辑查询操作与扩展搜索非常相配。

const result = fuse.search({
  $and: [
    { title: 'old war' }, // 模糊匹配 "old war"
    { color: "'blue" }, // 精确匹配 blue
    {
      $or: [
        { title: '^lock' }, // 以 "lock" 开头
        { title: '!arts' } // 不包含 "arts"
      ]
    }
  ]
})

约束与限制

在下述版本验证通过:

DevEco Studio 版本:4.0 Beta2(4.0.0.400),OpenHarmony SDK:API 10(4.0.9.6)。

目录结构

|---- FusejsDemo  # Demo 项目
|     |---- entry   # 示例代码文件夹
|           |---- src
|                |---- main/ets/pages      # Demo 页面
|                     |---- Index.ets      # Demo 主页
|                     |---- settings.ets   # 搜索选项设置页面
|                |---- ohosTest  # 库测试用例文件夹
|     |---- fusejs  # fuse.js 库文件夹
|           |---- build          # fuse.js 模块打包后的文件
|           |---- src            # 模块代码
|           |---- index.js       # 入口文件
|           |---- index.d.ts     # 声明文件
|           |---- *.json5        # 配置文件
|     |---- README.md          # 安装使用说明
|     |---- README.OpenSource  # 开源说明
|     |---- CHANGELOG.md       # 更新日志

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐