如果你刚使用我们的快速入门指南电影数据集体验了 Meilisearch,那么索引你的数据可能只需要几秒钟。但如果你处理的是更大的数据集,它可能花费的时间会长得多。在本文中,我们将回顾最佳实践,以帮助你高效地索引数据并加快索引过程。

定义你的需求

Meilisearch 以离散记录的形式存储数据,称为文档,每个文档必须有一个唯一的标识符——主键。文档被分组到集合中,称为索引

为了提供即时搜索体验,Meilisearch 需要以多种方式存储和组织数据,以便它能够以最有效的方式检索数据。因此,文档必须在准备好被搜索之前进行彻底的处理。

Meilisearch 中每个索引大约有二十个数据结构,构建它们是索引过程中最耗时的部分。更改索引设置可能会使许多这些数据结构失效,并需要重新索引你的数据。因此,在添加文档之前定义索引设置通常是一个好主意。

可搜索属性

默认情况下,添加到 Meilisearch 的所有文档字段都是可搜索的。但是,列在可搜索属性中的字段中存在的词语是需要最多数据结构的——确切地说,需要 11 个数据结构。加快索引速度的一个好方法是确保可搜索属性列表中的所有属性都是你真正想要用于匹配查询词的属性。

例如,考虑一个包含带有图像 URL 的字段的文档。你可能希望将图像显示给用户,但我怀疑用户是否希望能够在 URL 中搜索查询词。不要忘记,并非所有显示的字段都需要可搜索!

指定哪些字段实际上需要被搜索不仅很重要,而且避免在可搜索字段中使用无意义、随机或唯一的价值也很重要。想象一下所有那些包含“https”、“www”、“com”或像“I77lHE”这样的值的数据库——在试图找到特定产品或电影时,这些值一点也不有用😱

说到这里:🤔 唯一值……这听起来耳熟吗?💡 主键!这是你可以安全地从可搜索属性列表中删除的另一个字段。

幕后

为了更好地理解自定义可搜索属性索引设置的重要性,让我们看一下可搜索属性需要的最大的数据结构。在我们提到的 11 个数据结构中,有三个构建起来需要最长时间:WORD_DOCIDSWORD_POSITION_DOCIDWORD_PAIR_PROXIMITY_DOCIDS

为了更好地理解每个数据结构是如何工作的,我们将使用以下文档集作为例子

{
    "id": 1,
    "description": "New York City is the most populous city in the USA"
},
{
    "id": 2,
    "description": "New York was named in honor of the Duke of York"
},
{
    "id": 3,
    "description": "Tel Aviv is the new most expensive city in the world"
}

WORD_DOCIDS 中,每个词语都与包含它的文档的主键相关联

  • “new” => [1, 2, 3]
  • “york” => [1, 2]

WORD_POSITION_DOCID 中,键是词语及其在文档中的位置。与键关联的值是这些词语在相同位置的文档。在上面的文档中,id 将是属性 0,description 将是属性 1

  • new(1,0) => [1, 2]:在文档 1 和 2 中,词语“new”位于属性 1,位置 0——它是属性 description 的第一个词语
  • new(1, 4) => [3]:在文档 3 中,“new”位于属性 1,位置 4

最后,在 WORD_PAIR_PROXIMITY_DOCIDS 中,Meilisearch 会跟踪索引中所有文档中词语对之间的距离。词语必须彼此相邻 8 个词语才能被存储,因为更远的词语不被认为是同一语境的一部分,因此不相关。

在上面的示例文档中,Meilisearch 会存储以下对

  • newyork1 => [1, 2]
  • newcity2 => [1]
  • newcity3 => [3]

附加到词语对的数字代表它们之间的距离

  • 1 表示词语是相邻的
  • 2 表示它们被一个词语隔开
  • 3 表示它们被两个词语隔开

正如你所看到的,每个新词语都代表着 Meilisearch 内部数据结构中的额外行。像唯一 ID 或 URL 字符串这样的值会导致数据库大幅增长——而且很可能是无必要地增长。

细化 Meilisearch 应该搜索哪些字段对于减少索引时间至关重要。它还可以提高相关性和搜索速度,因为结果不会被无关数据污染。

可过滤和可排序属性

某些字段不包含任何词语,但仍然可能是帮助用户找到他们所需结果的关键。这种类型的数据可能非常适合过滤和排序,而不是常规的基于文本的搜索。

可过滤属性是可以用作过滤器来细化搜索结果的属性。你可以使用它们来限制特定用户的搜索结果,或者创建允许用户根据他们选择的条件缩小结果列表的分面搜索界面。布尔型值非常适合做过滤器。

可排序属性是在搜索时用于排序的属性,这允许用户决定他们想要首先看到哪些文档。数值非常适合排序。

作为经验法则,如果你的数据集包含具有数值和布尔型字段值的文档,请花时间评估它们是否可以成为可过滤属性或可排序属性列表的一部分。

排名规则

排名规则负责搜索结果的相关性。Meilisearch 包含六个内置的排名规则

[
  "words",
  "typo",
  "proximity",
  "attribute",
  "sort",
  "exactness"
]

你还可以添加自定义规则,用于对这个列表进行升序和降序排序

[
  "words",
  "typo",
  "proximity",
  "attribute",
  "sort",
  "exactness",
  "price:asc"
]

与在搜索时用于排序的可排序属性不同,自定义排名规则用于设置默认顺序。

如果你需要这种默认排序,最好事先配置好它。在文档已经索引后添加新的规则会触发重新索引,并且可能还会让你心烦意乱!

缩小规模,批量处理

只索引你真正需要的内容。你的数据库中的所有列都是必要的吗?数据集中的列越少,文档就越小。文档越小,它们的重量就越轻,到达 Meilisearch 的速度就越快,然后 Meilisearch 就能更快地处理它们。

Meilisearch 将连续的文档添加请求合并到单个批次中,并一起处理它们。这极大地加快了索引过程。由于每个批次的最终大小将取决于 Meilisearch 在处理最新文档添加请求时收到了多少数据,因此建议将文档分组发送,而不是逐个发送。

出于同样的原因,考虑压缩你的数据。Meilisearch 支持 brdeflategzip 压缩方法。你可以在我们的文档中找到更多信息。

保持最新状态,并让我们保持更新

使用最新的Meilisearch 稳定版本。新版本通常包含性能改进,可以显著提高索引速度。

如果你遇到任何索引问题,请报告!这是改进产品的重要步骤!

不要相信我,相信数据

在创建一些基准时,引擎团队的软件工程师Many创建了以下图表。请注意,索引时间高度依赖于机器的大小(CPU、内存)和数据集:对于大小相同的数据集,你可能会获得不同的结果。

Line graph that compares the indexing time with two different configurations (default and custom) in relation to the dataset size. In all cases, the speed is higher with a custom configuration.
横轴表示数据集的大小,纵轴表示索引时间

红线表示使用默认设置的索引时间,蓝线表示使用自定义配置的索引时间。在相同的机器和数据集上,我们观察到使用自定义设置时索引速度提高了 36%。

我们观察到数据库大小也获得了类似的改进,使用自定义设置时数据库大小明显更小

Bar graph of the database size where the database with custom settings is significantly smaller than the one with default settings.
蓝色表示使用自定义设置的数据库大小,红色表示使用默认设置的数据库大小

了解有关 Meilisearch 可以为你的业务带来什么的更多信息


以上就是今天要说的全部内容!我们涵盖了加快索引过程的最佳实践。你是否知道这些技巧?在遵循这些技巧之后,你是否注意到索引速度有变化?在我们的Discord上分享你的体验!

你的反馈对帮助我们改进 Meilisearch 至关重要!我再怎么强调都不为过,而且我从不厌倦重复它,因为这是事实。我们的社区与我们一起构建了 Meilisearch,并且继续帮助我们塑造它。

问题产品讨论 在 GitHub 上,我们的路线图,我们的Discord 服务器……无论在哪里,无论以何种方式,我们都希望听到你的声音!