如果您还没有听说,Meilisearch v0.22 已经发布,它带来了一个备受期待的新功能:搜索时的排序。

搜索时排序是指根据查询时决定的参数对结果进行排序。默认情况下,Meilisearch 根据结果的 相关性 对结果进行排序,但您可以对其进行配置,以便用户可以在搜索时决定他们希望首先看到哪些结果。

让我向您展示此功能有多强大。如果我想搜索 MacBook 并按价格升序对结果进行排序,我会发送以下查询

curl \
  -X POST 'http://localhost:7700/indexes/computers/search' \
  --data '{
    "q": "MacBook",
    "sort": [
        "price:asc"
    ]
}'

我可以做相反的事情,按降序价格搜索。我只需要在我的请求中用 desc 替换 asc

旧方法

在 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 问题,我们的产品经理在其中解释了这种选择。

经过这些修改,上面的大块代码已缩减为以下一行

// 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'
}"
/>

如您所见,我们不再使用 3 个不同的索引(artWorksartWorksAscartworksDesc),而只需要将属性名称附加到 artWorks 索引后跟所需的排序顺序 ascdesc

'artWorks:DateToSortBy:asc'
'artWorks:DateToSortBy:desc'

就是这样。流畅而简单。您可以在 此处 进行测试。

使用查询“Magritte”按升序,然后按降序日期排序的网络界面 gif

最终用户可能不会注意到区别,但在资源方面,它要高效得多。

v0.22 的另一个重大优势是新的索引器。它比以前快得多,所以如果您仍在使用旧版本的 Meilisearch,我强烈建议您 升级它

演示源代码可在 GitHub 上找到。我邀请您试用它,您可以添加其他要排序的属性,只要它们是字符串或数值即可。有关排序的更深入解释,请查看文档的 专门部分


图片来自 Héctor J. RivasUnsplash