過去記事を読み返していて検索インデックスの更新には言及しているものの、キーワード検索を Twig テンプレートで実装すること自体には触れていませんでした。
Searching | Craft CMS Documentation | 4.x
https://craftcms.com/docs/4.x/searching.html
そこで改めて Craft CMS でキーワード検索をする方法について、おさらいしてみたいと思います。
これは Craft CMS Advent Calendar 2022 25日目の記事です。
キーワード検索を実装するには
Craft CMS のテンプレートでキーワード検索をする場合、次の2つのステップが必要です。
URL パラメータから検索キーワードを取得
craft.app.request.getQueryParam
で任意の URL パラメータを取得し、変数にセットします。
{% set searchQuery = craft.app.request.getQueryParam('q') %}
サンプルは検索フォームの input[name="q"]
にキーワードをセット後、検索結果ページに遷移している想定です。
指定されたキーワードでエントリを検索
前段でセットした変数を .search()
の引数とし、エントリを検索します。.orderBy('score')
を追加しておくことで、検索結果は指定されたキーワードと関連性が高い順になります。
{% set searchResults = craft.entries()
.search(searchQuery)
.orderBy('score')
.all() %}
検索結果をページ分割したい場合は、.all()
の代わりに {% pagenate %}
タグを利用します。
キーワード構文について
.search()
にセットするキーワードをあらかじめ整形しておくことで、より細かい条件を指定できます。管理画面の検索ボックスでも同様に処理されます。
キーワード構文 | ヒットするエレメント |
---|---|
salty | 「salty」を含む |
salty dog | 「salty」と 「dog」を両方含む |
salty OR dog | 「salty」または 「dog」(もしくは、両方)を含む |
salty -dog | 「salty」を含むが 「dog」を含まない |
"salty dog" | 「salty dog」という正確なフレーズを含む |
body:salty | body フィールドに 「salty」を含む |
body:salty body:dog | body フィールドに 「salty」と 「dog」を両方含む |
body:salty OR body:dog | body フィールドに 「salty」または 「dog」を含む |
body:salty -body:dog | body フィールドに 「salty」を含むが「dog」を含まない |
body:"salty dog" | body フィールドに 「salty dog」という正確なフレーズを含む |
body::salty | body フィールドに 「salty」だけがセットされている |
body::"salty dog" | body フィールドに 「salty dog」だけがセットされている |
*ty | 「ty」で終わる単語を含む |
*alt* | 「alt」を含む単語を含む |
body:*ty | body フィールドに「ty」で終わる単語を含む |
body:*alt* | body フィールドに「alt」を含む単語を含む |
body::salty* | body フィールドに「salty」で始まる単語を含む |
body::*dog | body フィールドが「dog」で終わる |
body:* | body フィールドが何らかの値を持つ |
-body:* | body フィールドが空 |
なお、これらはあくまでデータベースに保存されている検索インデックスを対象とするテキスト検索で有効となる構文です。
日付や数値の範囲で検索する場合は、Craft CMS で日付や数値を指定してエントリを絞り込むも参考にしてください。
検索インデックスの登録内容を確認する
自分が試した範囲だと、Matrix フィールドの個々のブロックを foo.bar:*
のような形で検索することはできないようです。とはいえ、Matrix フィールド自体で「このフィールドの値を検索キーワードとして使用する」を有効にしてあれば、フィールド全体を対象としたキーワード検索が可能です。
これらはシステムの設定によって左右されてしまうため、どのフィールドで絞り込みができそうか次の SQL で確認してみるのがオススメです。
SELECT
f.handle,
si.keywords,
e.type,
si.fieldId,
si.attribute,
f.name,
f.context
FROM searchindex AS si
LEFT JOIN fields AS f ON f.id = si.fieldId
LEFT JOIN elements AS e ON e.id = si.elementId
WHERE
si.keywords != '' AND
si.fieldId NOT IN (0) AND
f.context IN ('global')
ORDER BY
e.type ASC,
si.fieldId ASC
実行結果は次のようになります。
ここから、カテゴリ(craft\elements\Category
)やエントリ(craft\elements\Entry
)を対象とする場合、text_singleLine:*
のように絞り込みが可能であることを判断できます。
最後に
今回は Craft CMS でキーワード検索する方法をおさらいしてみました。
以前も記事にした気がしていたものの、どうやら公式ドキュメントを翻訳したときと記憶が混ざっているようです(。-_-。)
そう考えると、基本的な内容でも改めてまとめた方が良いことがありそうですね。