Meilisearch v1.14 发布啦 ✨ 在我们的博客上阅读更多

回到首页Meilisearch 的标志
返回文章
2023 年 8 月 9 日

如何使用第二个索引实现文档加权

了解如何使用 Meilisearch 通过第二个索引为置顶文档实现提升搜索结果。

Laurent Cazanove
Laurent Cazanove开发者体验工程师StriftCodes
How to implement document boosting with a second index

在本指南中,我们将引导您完成使用 Meilisearch 实现提升搜索结果的过程。我们的目标是在某些关键词与用户查询匹配时,优先显示特定文档的搜索结果。这些加权的文档应该在搜索结果的顶部返回。

本指南解释了如何在后端实现提升文档。对于前端优先的实现,请参阅使用 React InstantSearch 实现提升搜索结果

概述

以下是关于如何使用第二个索引为“置顶文档”和 多重搜索功能实现文档加权的简化分解

  1. 创建索引: 设置两个索引:一个用于常规搜索,另一个用于提升结果。提升索引将有一个特殊的属性,keywords,用于触发加权。
  2. 填充“games”索引: 使用提供的 JSON 文件,用您的数据集填充 games 索引。此索引将作为我们提升文档的来源。
  3. 配置“pinned_games”索引: 配置 pinned_games 索引以显示属性而不显示关键词。相应地调整可搜索和显示的属性。
  4. 提升文档: 识别您想要提升的文档,并为其分配相关的关键词。例如,您可以为游戏 Counter-Strike 分配关键词 fpsshooter
  5. 实现多重搜索: 利用 Meilisearch 的多重搜索功能,跨常规索引和提升索引执行搜索查询。这样,匹配关键词的提升文档将首先出现。
  6. 显示结果: 以用户友好的格式呈现搜索结果,并使用视觉指示器突出显示提升的文档。

实施

安装

在深入探讨之前,请确保您已启动并运行 Meilisearch。如果您尚未安装,请按照以下步骤操作

  1. 启动 Meilisearch 实例 — 您可以在本地运行 Meilisearch 或通过 Meilisearch Cloud 运行。
  2. 确保您已安装您喜欢的语言 SDK(或框架集成)。

本指南使用 Python SDK,但它与任何其他 Meilisearch 集成的工作方式相同。🎉

初始化索引

在我们的示例中,我们将使用 Steam 游戏数据集。您可以将此过程调整为您自己的数据

  1. 为我们的 Steam 游戏数据集下载 steam-games.jsonsettings.json 文件
  2. 通过添加文档steam-games.json 文件中将数据集加载到您的 Meilisearch 实例中。

games 索引

import meilisearch
import json
from typing import Callable

client = meilisearch.Client(url="http://localhost:7700")
games = client.index("games")

# helper to wait for Meilisearch tasks
def wait_with_progress(client: meilisearch.Client, task_uid: int):
    while True:
        try:
            client.wait_for_task(task_uid, timeout_in_ms=1000)
            break
        except meilisearch.errors.MeilisearchTimeoutError:
            print(".", end="")
    task = client.get_task(task_uid)
    print(f" {task.status}")
    if task.error is not None:
        print(f"{task.error}")
            
print("Adding settings...", end="")
with open("settings.json") as settings_file:
    settings = json.load(settings_file)
    task = games.update_settings(settings)
    wait_with_progress(client, task.task_uid)


with open("steam-games.json") as documents_file:
    documents = json.load(documents_file)
    task = games.add_documents_json(documents)
    print("Adding documents...", end="")
    wait_with_progress(client, task.task_uid)

pinned_games 索引

此索引将包含提升的文档。pinned_games 索引的设置与 games 索引相同,但以下差异除外

  • 唯一的 searchableAttributeskeywords 属性,其中包含触发该文档置顶的词语。
  • displayedAttributes 是文档的所有属性,但 keywords 除外(我们不想向最终用户显示关键词)
pinned = client.index("pinned_games")

print("Adding settings...", end="")
with open("settings.json") as settings_file:
    settings = json.load(settings_file)
    settings["searchableAttributes"] = ["keywords"]
    # all but "keywords"
    settings["displayedAttributes"] = ["name", "description", "id", "price", "image", "releaseDate", "recommendationCount", "platforms", "players", "genres", "misc"]
    task = pinned.update_settings(settings)
    # see `wait_with_progress` implementation in previous code sample
    wait_with_progress(client, task.task_uid) 

更新提升的文档索引

我们现在将使用 games 索引中我们想要提升的文档来填充索引。

例如,假设我们想将游戏 "Counter-Strike" 置顶到 "fps""first", "person", "shooter" 关键词。

counter_strike = games.get_document(document_id=10)
counter_strike.keywords = ["fps", "first", "person", "shooter"]

print("Adding pinned document...", end="")
task = pinned.add_documents(dict(counter_strike))
wait_with_progress(client, task.task_uid)

自定义搜索结果

现在,让我们创建一个函数来返回包含置顶文档的搜索结果。

from copy import deepcopy
from typing import Any, Dict, List
from dataclasses import dataclass

@dataclass
class SearchResults:
    pinned: List[Dict[str, Any]]
    regular: List[Dict[str, Any]]

def search_with_pinned(client: meilisearch.Client, query: Dict[str, Any]) -> SearchResults:
    pinned_query = deepcopy(query)
    pinned_query["indexUid"] = "pinned_games"
    regular_query = deepcopy(query)
    regular_query["indexUid"] = "games"
    results = client.multi_search([pinned_query, regular_query])
    # fetch the limit that was passed to each query so that we can respect that value when getting the results from each source
    limit = results["results"][0]["limit"]
    # fetch as many results from the pinned source as possible
    pinned_results = results["results"][0]["hits"]
    # only fetch results from the regular source up to limit
    regular_results = results["results"][1]["hits"][:(limit-len(pinned_results))]
    return SearchResults(pinned=pinned_results, regular=regular_results)

我们可以使用此函数来检索包含提升文档的搜索结果

results = search_with_pinned(client, {"q": "first person shoot", "attributesToRetrieve": ["name"]})

results 对象应如下所示

SearchResults(pinned=[{'name': 'Counter-Strike'}], regular=[{'name': 'Rogue Shooter: The FPS Roguelike'}, {'name': 'Rocket Shooter'}, {'name': 'Masked Shooters 2'}, {'name': 'Alpha Decay'}, {'name': 'Red Trigger'}, {'name': 'RAGE'}, {'name': 'BRINK'}, {'name': 'Voice of Pripyat'}, {'name': 'HAWKEN'}, {'name': 'Ziggurat'}, {'name': 'Dirty Bomb'}, {'name': 'Gunscape'}, {'name': 'Descent: Underground'}, {'name': 'Putrefaction'}, {'name': 'Killing Room'}, {'name': 'Hard Reset Redux'}, {'name': 'Bunny Hop League'}, {'name': 'Kimulator : Fight for your destiny'}, {'name': 'Intrude'}])

哒啦 🎉 您现在拥有一个搜索结果对象,其中包含两个数组:提升的结果和“常规”结果。

遇到困难?请随时在我们的 Discord 社区中寻求帮助。

更进一步

本教程探讨了一种实现提升结果的方法。另一种技术是在前端实现文档置顶;请查看我们的 React 实现指南。这种不同的方法的好处是它与 InstantSearch 兼容

两种技术都可以实现类似的结果。我们还计划将 提升文档集成到 Meilisearch 引擎中。请在之前的链接上提供您的反馈,以帮助我们确定其优先级。

要了解更多关于 Meilisearch 的信息,您可以订阅我们的新闻通讯。您可以通过查看路线图和参与我们的产品讨论来了解更多关于我们产品的信息。

如有其他任何问题,请加入我们在 Discord 上的开发者社区。

干杯!

Meilisearch indexes embeddings 7x faster with binary quantization

Meilisearch 通过二进制量化将嵌入索引速度提高 7 倍

通过将二进制量化与向量存储 Arroy 结合使用,在保持搜索相关性和效率的同时,大幅减少了大型嵌入的磁盘空间使用量和索引时间。

Tamo
Tamo2024 年 11 月 29 日
How to add AI-powered search to a React app

如何向 React 应用程序添加 AI 驱动的搜索

使用 Meilisearch 的 AI 驱动搜索构建 React 电影搜索和推荐应用程序。

Carolina Ferreira
Carolina Ferreira2024 年 9 月 24 日
Meilisearch is too slow

Meilisearch 速度太慢

在这篇博文中,我们将探讨 Meilisearch 文档索引器所需的增强功能。我们将讨论当前的索引引擎、其缺点以及优化性能的新技术。

Clément Renault
Clément Renault2024 年 8 月 20 日