Drupal 8 の Search モジュールの挙動について

著者
Kato83
作成日
2020/04/15 - 19:44
更新日
2023/03/02 - 01:21

Drupal標準のサイト内検索モジュールの挙動要約

ビューモードの検索インデックス( search_index )で出力されたHTMLからタグを除去したものを、検索モジュールの設定の"インデックス付けをする単語の最小文字数"で指定した文字数単位で簡易CJK処理を行った上(日本語及び韓国語の場合)でインデックスが作られている。

Nodeエンティティのモジュール側の処理

NodeSearch::indexNode | NodeSearch.php | Drupal 8.2.x | Drupal API にNodeで検索インデックスが作られる際の処理を見ることができる。

<?php
// 前略

$node_render = $this->entityTypeManager
  ->getViewBuilder('node');
foreach ($languages as $language) {
  $node = $node
    ->getTranslation($language
    ->getId());

  // Render the node.
  $build = $node_render
    ->view($node, 'search_index', $language
    ->getId());

// 後略

getViewBuilder と view の組み合わせでエンティティを search_index なビューモードでhtmlを出力していることがわかる。

Searchモジュール側の処理

SearchIndex::index | SearchIndex.php | Drupal 8.8.x | Drupal API ここでhtmlのタグを除去してインデックスを追加している。

これで、Nodeの各フィールド単位でインデックスを張っているのではなく、出力されたHTMLを元にインデックスを作っていることが理解いただけたかと思います。

Web ComponentsやVue Components(Custom elements)を使っている場合の対処法

<my-paragraph text="サンプルテキスト"></my-paragraph>

フロントエンド側が上記のようなマークアップ(Web ComponentsやVue Components)等の場合、タグの除去の時点でtext属性のサンプルテキストも消えてしまうのでインデックスに追加されず、サイト内検索でヒットしない問題が発生します。

node.html.twig の対処

node.html.twig 系のテンプレートをカスタマイズしている場合は、以下で対応ができます。

node.html.twig →node--default.html.twig にリネーム or node--search-index.html.twig を新規作成

node--{コンテンツタイプ}.html.twig node--{コンテンツタイプ}--default.html.twig にリネーム or node--type--search-index.html.twig を新規作成

node--{Node ID}.html.twig node--{Node ID}--default.html.twig にリネーム or node--{Node ID}--search-index.html.twig を新規作成

既存のテンプレートにviewmodeの指定がなければdefaultのviewmodeを指定してあげるか、search-indexなviewmode用のテンプレートを新規で作成してあげれば回避、対応ができる。

field.html.twig

field.html.twig はデフォルトではviewmodeでのテンプレートhookが存在しないので、独自で実装してあげるか、field.html.twigでviewmodeの値が渡されているので同一テンプレートファイル内で条件分岐をつけるのもありだと思います。

heming - Field template for display mode - Drupal Answers ← 独自で実装するなら

同一テンプレートファイル内で条件分岐をつけるなら以下ソースを参照。

{% set view_mode = element['#view_mode'] %}

{#
viewmodeが search_index ならテキスト直出力、それ以外はweb componentsの出力をする 
※実際にはサンプルテキストとかではなく、fieldの値を出力する
#}
{% if view_mode == 'search_index' %}
サンプルテキスト
{% else %}
<my-paragraph text="サンプルテキスト"></my-paragraph>
{% endif %}

まとめ

エンドユーザーが閲覧するコンテンツと、Searchモジュールが別々のビューモードに分けることができるが分かれば、よりサイト内検索の精度を高めることもできそうですね。

※例えば、サイト内では多次元配列のことを連想配列と記載するルールにしていてもサイト内検索で多次元配列と検索されることもありうるので、そのような関連キーワードや類似ワードをコンテンツ側で予め登録しておいてインデックスだけさせるという方法もできそう。

ひとまず、上記の方法でコンテンツで入力したキーワードがサイト内検索モジュールでヒットしないなどの問題は回避できるのではないかと思います。

Category