(图片来源:不列颠哥伦比亚大学)

👉
这篇文章最初由客座作者 Michiel Mulders 于 2020 年 11 月发布。当时,Meilisearch 处于 v0.15 版本。它已被 Carolina Ferreira 更新以使用 Meilisearch v1 版本。

Meilisearch JS 是一个用 JavaScript 编写的 Meilisearch 客户端。Meilisearch 是一个功能强大、快速、开源、易于使用和部署的搜索引擎。搜索和索引都高度可定制。诸如拼写容错、过滤器和同义词之类的功能开箱即用。

查看演示

本项目的目的是教您如何

  • 创建新索引
  • 修改索引设置
  • 向索引添加数据
  • 忽略停用词
  • 启用过滤器以更快地过滤数据

我们将直接使用 API 和 JavaScript 包装器来向您展示它们的工作原理。在本教程中,我们将使用一个很酷的诺贝尔奖获得者数据集来向您展示一些示例。

首先,让我们看看要求。

要求

以下是能够跟随本教程的要求

让我们从创建您的第一个索引开始。

项目设置和 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 结尾的属性,例如 prizeIdobjectId。如果您想使用不包含 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)

现在,让我们添加一些我们想要消除的 停用词。停用词是频繁出现的没有搜索价值的词。

例如,不存在名为 athe 的产品。为了提高搜索速度,我们希望避免搜索此类停用词。当用户查找搜索查询“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:定义过滤器

过滤器有许多用例,例如细化搜索结果和创建 分面搜索界面

过滤器最适合数字或 枚举。例如,诺贝尔奖是针对固定类别列表颁发的。这构成了一个很棒的过滤器。年份属性也是如此。

下面是添加 yearcategory 属性的过滤器的示例代码片段。您始终可以通过查看索引的设置来验证添加了哪些过滤器。

  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 允许组合多个条件。您可以通过使用 ANDOR 对基本条件进行分组来构建过滤器表达式。过滤器表达式可以写成字符串、数组或两者的混合。在文档中了解有关 过滤器表达式 的更多信息。

 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 加星 以表达您的喜爱!