(图片来源:不列颠哥伦比亚大学)
Meilisearch JS 是一个用 JavaScript 编写的 Meilisearch 客户端。Meilisearch 是一个功能强大、快速、开源、易于使用和部署的搜索引擎。搜索和索引都高度可定制。诸如拼写容错、过滤器和同义词之类的功能开箱即用。
查看演示。
本项目的目的是教您如何
- 创建新索引
- 修改索引设置
- 向索引添加数据
- 忽略停用词
- 启用过滤器以更快地过滤数据
我们将直接使用 API 和 JavaScript 包装器来向您展示它们的工作原理。在本教程中,我们将使用一个很酷的诺贝尔奖获得者数据集来向您展示一些示例。
首先,让我们看看要求。
要求
以下是能够跟随本教程的要求
- Node.js 安装
- 一个正在运行的 自托管的 Meilisearch 实例。不想设置自己的 Meilisearch 实例?试试我们的 Meilisearch 云 选项!
- cURL 用于从终端发送请求(Postman 也适用)
- Meilisearch-js 包装器和依赖项(请参阅 安装指南)。
让我们从创建您的第一个索引开始。
项目设置和 Meilisearch-js 安装
为了跟随本教程,我们需要设置我们的 JavaScript 项目并安装 Meilisearch-js。创建一个新文件夹并在您的终端中运行以下命令。
npm init -y
这将准备您的项目设置。接下来,我们可以添加 Meilisearch-js 依赖项。
npm install meilisearch
最后,让我们在您的项目中创建一个名为 index.js
的文件。我们将使用此文件添加我们的 JavaScript 代码。
touch index.js
很好,让我们开始吧!
步骤 1:创建您的第一个索引
首先,让我们从准备开始。我们假设您有一个 正在运行的 Meilisearch 实例,并且可以通过您的 localhost 或公共 IP 地址访问它。
重要:为了简单起见,我们不使用主密钥。主密钥允许您保护 Meilisearch 实例的所有 API 端点。我们强烈建议在生产环境中使用 Meilisearch 或通过公共可访问的 IP 地址(例如 DigitalOcean Droplet)托管时 设置主密钥。
要验证您是否可以访问您的 Meilisearch 实例,请尝试查询可用的索引。如果您还没有创建任何索引,您应该会看到一个空数组作为结果。下面是您可以从终端执行的 cURL 命令。
curl http://127.0.0.1:7700/indexes
现在,让我们编辑我们的 index.js
文件以创建一个连接对象。我们将使用此连接对象来创建我们的第一个索引。首先,我们需要导入 Meilisearch 依赖项。此外,host
属性接受 Meilisearch 实例的 IP 地址。
const { MeiliSearch } = require('meilisearch')
const main = async () => {
const client = new MeiliSearch({
host: 'http://127.0.0.1:7700'
})
const indexes = await client.getIndexes()
console.log(indexes)
}
main()
请注意,我们添加了一些额外的代码,这些代码使用 client
对象查询所有索引,然后打印结果。
要执行文件,您可以使用 node
命令运行它。
node index.js
最后,让我们创建我们的第一个索引。由于我们正在处理诺贝尔奖,让我们将索引命名为 prizes
。我们可以使用 createIndex
函数创建一个新索引。为了验证我们的索引是否已成功创建,让我们再次查询所有索引以查看新创建的索引。
const { MeiliSearch } = require('meilisearch')
const main = async () => {
const client = new MeiliSearch({
host: 'http://127.0.0.1:7700'
})
const indexes = await client.getIndexes()
console.log(indexes)
const indexCreationTask = await client.createIndex('prizes')
await client.waitForTask(indexCreationTask.taskUid)
const updatedIndexes = await client.getIndexes()
console.log(updatedIndexes)
}
main()
您应该会看到以下结果打印到您的终端。
{
results: [
Index {
uid: 'prizes',
primaryKey: null,
httpRequest: [HttpRequests],
tasks: [TaskClient]
}
],
offset: 0,
limit: 20,
total: 1
}
注意:Meilisearch 尚未为 prizes 索引设置主键。当我们在下一步添加数据时,主键将被自动选择,因为我们的数据集包含一个 id 字段。
索引创建了吗?很好!让我们探索诺贝尔奖数据集。
步骤 2:添加诺贝尔奖数据集
首先,让我们简要地探索一下数据集。我们在此示例中使用的原始数据集来自 nobelprize.org,但是,我们已经对数据集进行了轻微修改以适应我们的用例。
您可以在这里探索 修改后的数据集。数据的结构如下所示。
每个对象都包含一个用作主键的 ID。Meilisearch 将自动搜索以 id
结尾的属性,例如 prizeId
或 objectId
。如果您想使用不包含 id
的数据集,您仍然可以手动 设置主键。
此外,我们找到了诸如年份、类别、名字、姓氏、动机和份额之类的属性。
{
id: "991",
year: "2020",
category: "chemistry",
firstname: "Emmanuelle",
surname: "Charpentier",
motivation: "for the development of a method for genome editing",
share: "2"
}
现在,让我们使用 cURL 将数据集下载为 JSON 文件。我们使用 -o
属性来定义下载内容的输出文件。
curl -L https://raw.githubusercontent.com/meilisearch/demos/main/src/nobel-prizes/setup/prizes.json -o prizes.json
接下来,我们需要将数据集添加到 Meilisearch 实例。让我们将数据集上传到 prizes
索引。请注意,URL 有所不同,因为我们正在将 documents
添加到 prizes
索引:indexes/prizes/documents
。确保 --data
属性的文件名与您的 prizes JSON 文件的文件名匹配。
curl -i -X POST 'http://127.0.0.1:7700/indexes/prizes/documents' \
--header 'content-type: application/json' \
--data @prizes.json
要验证数据是否已成功上传,让我们查询所有文档。您应该会看到所有诺贝尔奖对象。
curl http://127.0.0.1:7700/indexes/prizes/documents
成功!接下来,让我们使用一些代码将额外文档添加到我们的 prizes
索引中。
步骤 2.1:使用 Meilisearch-js 客户端添加文档
我们刚刚使用终端添加了文档。现在是时候使用 JS 代码添加额外文档了。让我们定义一个数组,其中包含我们想要添加到 prizes
索引中的新文档。请注意,我们首先需要检索我们的索引,以便我们可以使用此索引对象添加文档。
const { MeiliSearch } = require('meilisearch')
const main = async () => {
const client = new MeiliSearch({
host: 'http://127.0.0.1:7700'
})
const index = client.index('prizes')
const documents = [
{
id: '12345',
year: '2021',
category: 'chemistry',
firstname: 'Your',
surname: 'Name',
motivation: 'for the development of a new method',
share: '1'
}
]
let response = await index.addDocuments(documents)
console.log(response)
// => EnqueuedTask {
// taskUid: 4170,
// indexUid: 'prizes',
// status: 'enqueued',
// type: 'documentAdditionOrUpdate',
// enqueuedAt: 2023-04-19T12:14:57.748Z
// }
}
main()
当您添加新文档时,Meilisearch 会返回一个包含 taskUid
的对象。使用 任务方法,您可以跟踪文档添加过程,直到它完成处理或失败。
在步骤 3 中,让我们学习如何搜索文档。
步骤 3:搜索诺贝尔奖文档
搜索文档非常简单。同样,我们首先需要检索索引对象。接下来,我们可以使用索引对象搜索特定查询。例如,我们正在查找 chemisytr
以展示 Meilisearch 的类型容错。
const { MeiliSearch } = require('meilisearch')
const main = async () => {
const client = new MeiliSearch({
host: 'http://127.0.0.1:7700'
})
const index = client.index('prizes')
const search = await index.search('chemisytr')
console.log(search)
}
main()
这将返回大量结果。让我们学习如何添加过滤器,例如限制结果数量。将以下行更改为添加一个接受过滤器的对象。
const search = await index.search('chemisytr', { limit: 1})
这将返回以下结果。
{
hits: [
{
id: '991',
year: '2020',
category: 'chemistry',
firstname: 'Emmanuelle',
surname: 'Charpentier',
motivation: '"for the development of a method for genome editing"',
share: '2'
}
],
query: 'chemisytr',
processingTimeMs: 1,
limit: 1,
offset: 0,
estimatedTotalHits: 111
}
接下来,我们想要修改 prizes 索引的设置以消除停用词。
步骤 4:修改索引设置以消除停用词
现在,让我们看看 prizes 索引的设置。您可以通过暴露的 API 访问设置,如下所示
curl http://localhost:7700/indexes/prizes/settings
您将看到以下结果,其中 stopWords
数组为空。
{
displayedAttributes: [ '*' ],
searchableAttributes: [ '*' ],
filterableAttributes: [],
sortableAttributes: [],
rankingRules: [ 'words', 'typo', 'proximity', 'attribute', 'sort', 'exactness' ],
stopWords: [],
synonyms: {},
distinctAttribute: null,
typoTolerance: {
enabled: true,
minWordSizeForTypos: { oneTypo: 5, twoTypos: 9 },
disableOnWords: [],
disableOnAttributes: []
},
faceting: { maxValuesPerFacet: 100 },
pagination: { maxTotalHits: 1000 }
}
我们可以使用 JavaScript 代码实现相同的目的,如下所示。
const index = client.index('prizes')
const settings = await index.getSettings()
console.log(settings)
现在,让我们添加一些我们想要消除的 停用词。停用词是频繁出现的没有搜索价值的词。
例如,不存在名为 a
或 the
的产品。为了提高搜索速度,我们希望避免搜索此类停用词。当用户查找搜索查询“a mask”时,Meilisearch 引擎将自动删除 a
部分并查找 mask
这个词。
在此示例中,我们想要消除以下停用词
- an
- the
- a
首先,让我们检查当查询 the
这个词时,我们收到了多少结果。
const index = client.index('prizes')
const results = await index.search('the')
console.log(results.estimatedTotalHits)
上面针对 the
的查询返回了 495 个匹配项。现在,让我们修改我们的 index.js
脚本以消除上述停用词。
const index = client.index('prizes')
const response = await index.updateSettings({
stopWords: ['a', 'an', 'the']
})
console.log(response)
为了验证我们设置更改的有效性,让我们再次查询 the
这个词。现在,此查询应该返回 218
个结果。很酷吧?
快速提示:您可能忘记了一个特定的停用词,例如 and
。如果您向您的 API 发送新的 updateSettings
请求,这将覆盖旧的配置。因此,请确保每次您想要进行更改时都发送完整的停用词列表。
让我们继续!
步骤 5:定义过滤器
过滤器有许多用例,例如细化搜索结果和创建 分面搜索界面。
过滤器最适合数字或 枚举。例如,诺贝尔奖是针对固定类别列表颁发的。这构成了一个很棒的过滤器。年份属性也是如此。
下面是添加 year
和 category
属性的过滤器的示例代码片段。您始终可以通过查看索引的设置来验证添加了哪些过滤器。
const index = client.index('prizes')
const response = await index.updateSettings({
filterableAttributes: ['category', 'year']
})
步骤 5.1:使用过滤器进行实验
现在,我想查询所有名为 Paul 的诺贝尔奖获得者。这将返回 14 个结果。
const index = client.index('prizes')
const search1 = await index.search('paul')
console.log(`Search 1 hits: ${search1.estimatedTotalHits}`) // 14
接下来,我想根据化学类别过滤结果。请注意,我们发送了一个带有请求的额外数据属性,该属性允许我们设置过滤器。此 过滤器属性 期望一个包含一个或多个条件的 过滤器表达式。
const index = client.index('prizes')
const search2 = await index.search('paul', { filter: 'category = "Chemistry"' })
console.log(`Search 2 hits: ${search2.estimatedTotalHits}`) ) // 5
此查询返回五个结果。
最后,我想添加一些额外的过滤器以根据类别和年份进行过滤。我想返回 1995 年、1996 年或 1997 年的诺贝尔奖获得者。幸运的是,Meilisearch 允许组合多个条件。您可以通过使用 AND
和 OR
对基本条件进行分组来构建过滤器表达式。过滤器表达式可以写成字符串、数组或两者的混合。在文档中了解有关 过滤器表达式 的更多信息。
const index = client.index('prizes')
const search3 = await index.search('paul', {filter: 'category = "Chemistry" AND (year = 1995 OR year = 1996 OR year = 1997)'})
console.log(`Search 3 hits: ${search3.estimatedTotalHits}`) // 2
最终,这将只返回两个满足我们需求的结果。
{
hits:[
{
id: '287',
year: '1997',
category: 'chemistry',
firstname: 'Paul D.',
surname: 'Boyer',
motivation:
'"for their elucidation of the enzymatic mechanism underlying the synthesis of adenosine triphosphate (ATP)"',
share: '4'
},{
id: '281',
year: '1995',
category: 'chemistry',
firstname: 'Paul J.',
surname: 'Crutzen',
motivation: '"for their work in atmospheric chemistry, particularly concerning the formation and decomposition of ozone"',
share: '3'
}
],
offset: 0,
limit: 20,
nbHits: 2,
exhaustiveNbHits: false,
processingTimeMs: 0,
query: 'paul'
}
不错!最后,让我们使用 Meilisearch 引擎的排名规则进行操作。
步骤 6:定义您自己的排名规则
在步骤 3 中,我们向您展示了 Meilisearch 如何处理错别字,方法是查询 chemisytr
而不是 chemistry
。
但是,您可能已经注意到,您的索引设置列出了许多不同的排名规则。 排名规则 定义了 Meilisearch 中的相关性。它们会影响结果的排名顺序。排名规则按重要性顺序从上到下排序。
您可以定义自己的排名规则。这很令人兴奋,对吧?让我们为 year
属性添加一个自定义排名规则。
您可以定义升序或降序排序规则。
const index = client.index('prizes')
await index.updateSettings({
rankingRules:
[
"year:desc",
"words",
"typo",
"proximity",
"attribute",
"sort",
"exactness"
]
})
接下来,让我们再次搜索 Paul
。现在,请注意,结果按预期按 year
属性排序。
[
{
id: '995',
year: '2020',
category: 'economics',
firstname: 'Paul',
surname: 'Milgrom',
motivation: '"for improvements to auction theory and inventions of new auction formats"',
share: '2'
},
{
id: '834',
year: '2008',
category: 'economics',
firstname: 'Paul',
surname: 'Krugman',
motivation: '"for his analysis of trade patterns and location of economic activity"',
share: '1'
},
{
id: '764',
year: '2003',
category: 'medicine',
firstname: 'Paul C.',
surname: 'Lauterbur',
motivation: '"for their discoveries concerning magnetic resonance imaging"',
share: '2'
},
…
]
就这样!
结论
这就是本 Meilisearch 和 JS 教程的全部内容。本教程教您如何使用 Meilisearch API、创建索引、修改索引设置以及定义过滤器以实现更准确、更快的搜索。
试用我们的实时 演示。
有关更多信息,请务必查看 文档 和 GitHub 上的 JS API 包装器。
喜欢使用 Meilisearch,请务必在 GitHub 上为 Meilisearch 加星 以表达您的喜爱!