排序的艺术

如果您还没听说,Meilisearch v0.22 已经发布了,它带来了一个备受期待的新功能:在搜索时排序。
搜索时排序是指根据查询时确定的参数对结果进行排序。默认情况下,Meilisearch 根据结果的相关性对结果进行排序,但您可以对其进行配置,以便用户可以在搜索时决定首先看到哪些结果。
让我向您展示这个功能有多么强大。如果我想搜索 MacBook 并按价格升序对结果进行排序,我将发送以下查询
curl -X POST 'http://localhost:7700/indexes/computers/search' --data '{ "q": "MacBook", "sort": [ "price:asc" ] }'
我可以反过来按价格降序搜索。我只需要在我的请求中将 asc
替换为 desc
。
旧方法
在 Meilisearch v0.22 之前,您只能使用自定义排名规则对搜索结果进行排序。
借助自定义排名规则,我们可以按我们选择的数字属性对搜索结果进行排序。但是,排序不是在搜索时进行的,排序顺序是在我们的索引设置中决定的。
为了更改用户界面中搜索结果的排序顺序,我们必须复制索引并为每个索引设置不同的自定义排名规则。
这就是几个月前我在我们的 MoMA 演示中所做的事情。对于那些错过它的人,MoMA 演示是使用现代艺术博物馆的艺术品数据集创建的 Meilisearch 演示,该数据集可在他们的 GitHub 仓库中找到。您可以在 这篇博客文章中了解有关演示的更多信息,我希望用户能够按日期对艺术品进行排序,因此我不得不创建三个索引
- artWorks
,使用默认的内置排名规则
- artWorksAsc
,使用自定义排名规则进行升序排序
- artWorksDesc
,使用自定义排名规则进行降序排序
// Get or create indexes const artWorksIndex = await client.getOrCreateIndex('artWorks', { primaryKey: 'ObjectID' }) const artWorksAscIndex = await client.getOrCreateIndex('artWorksAsc', { primaryKey: 'ObjectID' }) const artWorksDescIndex = await client.getOrCreateIndex('artWorksDesc', { primaryKey: 'ObjectID' }) const defaultRankingRules = [ 'typo', 'words', 'proximity', 'attribute', 'exactness' ] const rankingRulesAsc = [ 'typo', 'words', 'proximity', 'attribute', 'exactness', 'asc(DateToSortBy)' // ascending sort ] const rankingRulesDesc = [ 'typo', 'words', 'proximity', 'attribute', 'exactness', 'desc(DateToSortBy)' // descending sort ]
由于 Meilisearch 速度极快,这种复制或三倍复制给人一种在搜索时排序的印象。
当时,排序在我们的 路线图的“考虑中”选项卡中,并且是最受投票的功能之一(86 票)。
我们有一个 公开路线图,您可以在其中提交功能或集成想法,并为现有想法投票。
使用新的 v0.22 排序功能
今天,这已成为现实。我已经更新了演示以集成此功能。让我们来看看发生了哪些变化。
幕后
首先,我在设置中添加了以下行
sortableAttributes: ['DateToSortBy']
此添加是必要的,因为我们需要告知 Meilisearch 我们要用于排序的属性。
我们只需要一个索引(而不是三个)和默认排名规则。这大大减少了后端代码。您可以更改 sort
规则的位置,以根据您的需求调整搜索结果的相关性。默认情况下,sort
规则在排名规则的第 5 位,以提升与用户搜索相关的结果。
您可以在此处了解有关排名规则及其如何影响相关性的更多信息。
如果您好奇为什么 sort
规则默认位于第 5 位,您可以查看 此 GitHub issue,我们的产品经理在其中解释了这一选择。
通过这些修改,上面的大段代码已简化为以下行
// Get or create the index const index = await client.getOrCreateIndex('artWorks', { primaryKey: 'ObjectID' })
很简单,对吧?但是,前端呢?
焦点
对于此演示,我使用了 Vue InstantSearch,并结合了 Instant Meilisearch。这会将 Meilisearch 实例与开源 InstantSearch 前端工具连接起来,使我们能够轻松自定义搜索环境。
之前的代码看起来像这样
<ais-sort-by :items="[ { value: 'artWorks', label: 'Featured' }, { value: 'artWorksAsc', label: 'Date asc.' }, { value: 'artWorksDesc', label: 'Date desc.' } ]" :class-names="{ 'ais-SortBy': 'MyCustomSortBy' }" />
我只需要将其转换为这样
<ais-sort-by :items="[ { value: 'artWorks', label: 'Featured' }, { value: 'artWorks:DateToSortBy:asc', label: 'Date asc.' }, { value: 'artWorks:DateToSortBy:desc', label: 'Date desc.' } ]" :class-names="{ 'ais-SortBy': 'MyCustomSortBy' }" />
如您所见,我们只需要将属性名称附加到 artWorks
索引,后跟所需的排序顺序 asc
或 desc
,而不是使用 3 个不同的索引(artWorks
、artWorksAsc
和 artworksDesc
)。
'artWorks:DateToSortBy:asc' 'artWorks:DateToSortBy:desc'
就是这样。流畅而简单。您可以在此处进行测试。
Web 界面,查询“Magritte”,按日期升序和降序排序 gif
最终用户可能不会注意到差异,但从资源角度来看,它效率更高。
v0.22 的另一个巨大优势是新的索引器。它比以前快得多,因此如果您仍在使用旧版本的 Meilisearch,我强烈建议您升级它。
演示源代码可在 GitHub 上找到。我邀请您试用它,您可以添加其他属性进行排序,只要它们是字符串或数值即可。有关排序的更深入解释,请查看文档的专用部分。
图片由 Héctor J. Rivas 在 Unsplash 上提供