如何在 Drupal 9 中實現 Algolia Search(第 2 部分)

已發表: 2022-09-13

在本系列的前一章中,我們向您介紹了配置 Algolia 儀表板和您的 Drupal 站點以索引 Algolia 上的站點內容的過程。 在本章中,您將學習如何在您的 Drupal 網站上顯示 Algolia 搜索結果。

要顯示搜索結果,您需要創建一個 Drupal 自定義塊並將該塊放在/search頁面上。 此外,您還將了解如何使用 Algolia 的InstantSearch庫。 請注意,此過程假設您對如何在 Drupal 中創建自定義模塊有基本的了解,因此我們不會深入探討創建自定義模塊的過程。 閱讀本文以了解如何在 Drupal 9 中以編程方式創建自定義模塊。

這是 2 部分系列文章的第二章。 單擊此處閱讀我們討論如何配置 Algolia 和 Drupal 的第一部分。

如何在 Drupal 9 中實現 Algolia Search(第 2 部分)

為界面構建自定義塊

我們將使用以下結構來創建我們的自定義塊。

 algolia_search_interface - js/ - algolia.js - src/ - Plugin - Block - DemoSearchBlock.php - templates/ - algolia_search_interface-block.html.twig - algolia_search_interface.info.yml - algolia_search_interface.libraries.yml - algolia_search_interface.module

聲明庫

如前所述,我們將使用 Algolia 的 InstantSearch 庫來訪問搜索結果。 因此,讓我們在 algolia_search_interface.libraries.yml 中聲明所有庫,如下所示:

 algolia-javascript: js: https://cdn.jsdelivr.net/npm/[email protected]/dist/algoliasearch-lite.umd.js : { type: external } https://cdn.jsdelivr.net/npm/[email protected] : { type: external } js/algolia.js: {preprocess: false} dependencies: - core/drupalSettings css: theme: https://cdn.jsdelivr.net/npm/[email protected]/themes/algolia-min.css: { type: external, minified : true }

訪問和設置變量

在演示搜索塊 (DemoSearchBlock.php)​​中,我們將簡單地從 Drupal 配置中訪問 Algolia 變量,並使用以下代碼將它們分配給 drupalSettings:

 public function build() { // Get Algolia config. $config = $this->configFactory->get('search_api.server.algolia_search'); $app_id = $config->get('backend_config.application_id'); $api_key = $config->get('backend_config.api_key'); $index_name = $this->configFactory->get('search_api.index.vehicles_data')->get('options.algolia_index_name'); return [ '#theme' => 'demo_search_block', '#attached' => [ 'library' => 'algolia_search_interface/algolia-javascript', 'drupalSettings' => [ 'app_id' => $app_id, 'index_name' => $index_name, 'api_key' => $api_key, ], ], '#cache' => [ 'contexts' => [ 'url.path', 'url.query_args', ], ], ]; }

添加模板

現在您需要為自定義塊添加模板。 因此,讓我們在 algolia_search_interface.module 中為我們的自定義塊定義 hook_theme:

 /** * Implements hook_theme(). */ function algolia_search_interface_theme($existing, $type, $theme, $path) { return [ 'demo_search_block' => [], ]; }

定義容器

現在,讓我們定義我們的模板數據來呈現搜索結果。 我們將簡單地定義 InstantSearch 庫將呈現結果的容器。 我們將在 algolia_search_interface-block.html.twig 中添加 4 個容器:

 - Searchbox (#searchbox) - Search results (#hits) - Facets (#filter-widget) - Pagination (#pagination)
 <div class="demo-instant-search"> <div class="algolia-searchbox"></div> <div class="align-left"> <div class="filter-header">{{ 'Manufacturer'|t }}</div> <div></div> </div> <div class="right-col"> <div></div> </div> </div> <div></div>

顯示搜索結果

現在,您擁有了顯示搜索結果所需的所有要素。 那麼讓我們看看如何使用 InstantSearch 來顯示我們的結果。

首先,讓我們從 drupalSettings 變量中獲取索引名稱、應用程序 ID 和應用程序鍵。 我們需要將它們傳遞給 algolia.js 中的 Algolia API。

 const index_name = drupalSettings.index_name; const app_id = drupalSettings.app_id; const api_key = drupalSettings.api_key;

準備好應用程序鍵和索引名稱後,您需要初始化並啟動 InstantSearch。

 const search = instantsearch({ indexName: index_name, searchClient: algoliasearch(app_id, api_key), }); search.start();

此時,您不會在搜索頁面中看到任何差異,因為您尚未將任何小部件添加到 InstantSearch。 因此,讓我們在即時搜索中添加一個搜索框小部件。

 search.addWidget( instantsearch.widgets.searchBox({ container: '#searchbox', }) );

請注意,我們使用了InstantSearchaddwidget()函數來添加單個小部件。 當使用多個小部件時, addwidget()是不可行的。 您將需要以下列方式使用它:

 search.addWidgets([ instantsearch.widgets.searchBox({ container: '#searchbox', }), instantsearch.widgets.hits({ container: '#hits' }), ]);

現在您將能夠在搜索頁面上看到搜索結果。 但正如我們所見,結果是非常原始的格式:

Algolia 搜索結果 - 原始格式

為了改進這一點,讓我們使用模板屬性格式化結果,如下所示:

 instantsearch.widgets.hits({ container: '#hits', templates: { item: ` <h3 class="title">{{{title.value}}}</h3> <p class="detail"> {{{field_manufacturer}}} </p> <p class="uri">{{{uri}}} </p> `, }, }),

請注意,雖然結果看起來不錯,但有時我們需要對數據進行一些處理,然後才能將其顯示在頁面上。 例如在上面的代碼中,URI 值是`public://`格式。 在這裡,我們可以使用transformItems屬性來根據我們的要求更改結果。

 instantsearch.widgets.hits({ container: '#hits', transformItems(items) { return items.map(item => ({ ...item, url: item.uri.replace('public://', /sites/default/files/'), })); }, templates: { item: ` <h3 class="title">{{{title.value}}}</h3> <p class="detail"> {{{field_manufacturer }}} </p> <p class="uri">{{{url}}} </p> `, }, })

一旦結果集就位,您現在可以移動以顯示構面數據以過濾我們的搜索條件。 您將使用相同的addWidgets()函數來顯示構面。

 search.addWidgets([ instantsearch.widgets. refinementList({ container: '#filter-widget, attribute: 'field_manufacturer', }), ]);

屬性選項定義了我們想要顯示分面的字段名稱。 請記住,這也需要在 Algolia 儀表板中進行預配置。

最後,讓我們添加分頁以顯示更多結果。

 search.addWidgets([ instantsearch.widgets. pagination({ container: '#pagination, }), ]);

我們完成了! 這就是最終代碼的樣子

const index_name = drupalSettings.index_name; const app_id = drupalSettings.app_id; const api_key = drupalSettings.api_key; if(index_name && app_id && api_key) { const search = instantsearch({ indexName: index_name, searchClient: algoliasearch(app_id, api_key), }); search.addWidgets([ instantsearch.widgets.searchBox({ container: '#searchbox', }), instantsearch.widgets.hits({ container: '#hits', transformItems(items) { return items.map(item => ({ ...item, url: item.uri.replace('public://', '/sites/default/files/'), })); }, templates: { item: ` <h3 class="title">{{{_highlightResult.title.value}}}</h3> <p class="detail"> {{{_highlightResult.field_manufacturer.value}}} </p> <p class="uri"><img src="{{{url}}}" /></p>`, }, }), instantsearch.widgets.refinementList({ container: '#filter-widget', attribute: 'field_manufacturer', }), instantsearch.widgets.pagination({ container: '#pagination', }) ]); search.start(); } else { throw "Algolia settings missing";}

最後的想法

當我們結束我們的兩部分文章系列時,我們希望您對 Algolia 有足夠的了解。 我們已經介紹瞭如何將 Algolia 搜索與 Drupal 集成以構建強大的消費級搜索。 我們還討論了使用 InstantSearch 庫來自定義搜索結果。 正在尋找一家 100% 專注於 Drupal 的公司,可以幫助您建立雄心勃勃的 Drupal 體驗,同時利用網絡的精華? 我們很樂意聽取您的意見!