AI 驅動的混合搜尋目前為封閉測試階段。加入候補名單以取得搶先體驗!

前往首頁Meilisearch 的標誌
返回文章列表
2023 年 8 月 9 日

如何使用第二索引實作文件加強 (Document Boosting)

了解如何使用 Meilisearch,透過第二個索引來實作置頂文件的優先搜尋結果。

Laurent Cazanove
Laurent CazanoveDX 工程師 & 文案@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. 加強文件:找出您想要加強的文件,並為其分配相關的關鍵字。例如,您可以將關鍵字 fpsshooter 分配給遊戲 Counter-Strike
  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="https://127.0.0.1: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上的開發人員社群。

乾杯!

How to add AI-powered search to a React app

如何在 React 應用程式中新增 AI 驅動的搜尋

使用 Meilisearch 的 AI 驅動的搜尋,建立 React 電影搜尋和推薦應用程式。

Carolina Ferreira
Carolina Ferreira2024 年 9 月 24 日
Build your Next.js Shopify storefront with Blazity

使用 Blazity 建置您的 Next.js Shopify 店面

了解如何使用 Next.js 和 Blazity commerce starter 建置 Shopify 店面。

Laurent Cazanove
Laurent Cazanove2024 年 8 月 19 日
Meilisearch 1.8

Meilisearch 1.8

Meilisearch 1.8 帶來了負關鍵字搜尋、搜尋穩健性和 AI 搜尋的改進,包括新的嵌入器。

Carolina Ferreira
Carolina Ferreira2024 年 5 月 7 日