2026年5月20日

2026年5月20日

WordPressの日本語検索でヒットしない原因と改善方法|表記ゆれ・全角スペース・全文検索

WordPressの標準検索は、日本語でも部分一致で動きます。それでも「ワードプレス」で「WordPress」の記事が出ない、「設定 方法」(全角スペース)で何も出ない、といったことが起こるのは、検索の仕組みと表記の違いが原因です。この記事では、2026年10月時点のWordPressとMySQL 8.0以降・MariaDBを前提に、標準検索の動きを確かめたうえで、原因ごとの改善方法を説明します。コードはWordPress 7.1とMySQL 8.4の環境で動作を確認しています。

WordPressの標準検索の仕組み

検索窓に入力された語は、次のように処理されます。

  1. 半角スペース(とタブ、カンマ、プラス記号)で区切られて、複数の語に分かれます。" で囲んだ部分は1語として扱われます。
  2. 語ごとに、タイトル・抜粋・本文のどれかに含まれるかを LIKE '%語%' で調べます。つまり部分一致です。「設定方法」で検索すると、「メールの設定方法」を含む記事も見つかります。
  3. 語が複数あるときは、すべての語を含む記事だけが残ります(AND検索)。-語 と書くと、その語を含む記事を除外できます。
  4. ログインしていない訪問者には、パスワード保護された投稿は検索結果に出ません。

このため、日本語の検索がうまくいかない主な原因は「部分一致が効かないこと」ではなく、次のどれかです。

症状 原因
「ワードプレス」で「WordPress」の記事が出ない 文字列が違う。標準検索に同義語の辞書はない
「設定 方法」で何も出ない 全角スペースは区切りにならず、「設定 方法」という1語として探している
「設定方法」で「設定の方法」が出ない 「設定方法」という連続した文字列を探しているため。単語の分解(形態素解析)はしない
「プラグイン」(半角)で「プラグイン」が出ない 濁点付きの半角カナは2文字で表されるため、文字ごとの比較で一致しない
ひらがなとカタカナが区別される、されない データベースの照合順序(collation)によって変わる
記事が増えて検索が遅い LIKE '%語%' は索引を使えず、全件を調べる

まず照合順序を確認する

ひらがなとカタカナ、全角と半角の英数字を同じ文字として扱うかどうかは、WordPressのコードではなく、データベースの照合順序で決まります。投稿テーブルの照合順序を確認します。

wp db query "SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = '$(wp db prefix)posts';"

phpMyAdmin を使う場合は、データベースを選んで同じSQLを実行するか、wp_posts テーブルの「操作」タブで確認できます。MySQL 8.4 と MariaDB 11.8 で LIKE の結果を確かめたところ、次のようになりました。

照合順序 ひらがな=カタカナ 全角英字=半角英字 大文字=小文字
utf8mb4_unicode_520_ci 同じとみなす 同じとみなす 同じとみなす
utf8mb4_unicode_ci 同じとみなす 同じとみなす 同じとみなす
utf8mb4_0900_ai_ci(MySQL 8.0以降) 同じとみなす 同じとみなす 同じとみなす
utf8mb4_general_ci 区別する 区別する 同じとみなす

現在のWordPressが作るテーブルは、多くの環境で utf8mb4_unicode_520_ci です。この場合、「ぷらぐいん」で「プラグイン」の記事も見つかります。一方で、「ハ」と「パ」のように濁点・半濁点の有無も区別しないため、意図しない記事がヒットすることもあります。

古いサイトで utf8mb4_general_ci になっている場合、ひらがなとカタカナは区別されます。照合順序の変更はテーブル全体に影響する作業なので、行う場合はバックアップを取り、テスト環境で確認してからにしてください。

検索語を正規化する(全角スペース・半角カナ)

全角スペースと半角カナは、検索語の側を直すだけで改善できます。PHPの mb_convert_kana() を使います。主なオプションは次のとおりです。

オプション 変換内容
s 全角スペース → 半角スペース
a 全角英数字・記号 → 半角
K 半角カタカナ → 全角カタカナ
V 濁点・半濁点付きの文字を1文字にまとめる(K と組み合わせて使う)
c 全角カタカナ → 全角ひらがな
H 半角カタカナ → 全角ひらがな

H は「カタカナをひらがなにする」オプションではなく、半角カタカナだけを対象にします。また、検索語だけをひらがなに変えると、本文がカタカナで書かれている記事は、照合順序によっては見つからなくなります。検索語の正規化は、本文の書き方に影響されない全角スペースと半角カナに絞るのが安全です。

次のコードを wp-content/mu-plugins/jp-search-normalize.php として保存します(テーマの functions.php に書いてもかまいません)。

<?php
/**
 * Plugin Name: 検索語の正規化
 */

add_action(
	'pre_get_posts',
	function ( $query ) {
		if ( is_admin() || ! $query->is_main_query() || ! $query->is_search() ) {
			return;
		}

		$s = (string) $query->get( 's' );
		if ( '' === $s ) {
			return;
		}

		// s: 全角スペース→半角スペース
		// K: 半角カタカナ→全角カタカナ、V: 濁点・半濁点を1文字にまとめる
		$s = mb_convert_kana( $s, 'sKV', 'UTF-8' );
		$s = trim( preg_replace( '/\s+/u', ' ', $s ) );

		$query->set( 's', $s );
	}
);

これで「設定 方法」は「設定」と「方法」の2語として、「プラグイン」は「プラグイン」として検索されます。WordPressの日本語版で使われることの多い「WP Multibyte Patch」プラグインも、検索語の全角スペースを半角に変換する処理を行っています。このプラグインを有効にしている場合、全角スペースの対応は重複しますが、害はありません。

スペース区切りをOR検索にする

標準ではすべての語を含む記事だけが出ます(AND検索)。「どれかを含む記事」を出したい場合は、posts_search フィルターで検索条件を組み直します。

posts_search は、検索条件の部分(AND (...) の部分)だけを受け取るフィルターです。posts_where を使うと、投稿タイプや公開状態の条件を含むWHERE句全体を受け取るため、丸ごと置き換えると下書きや非公開の投稿まで検索結果に出てしまいます。検索条件を変えるときは posts_search を使ってください。

<?php
/**
 * Plugin Name: スペース区切りをOR検索にする
 */

add_filter(
	'posts_search',
	function ( $search, $query ) {
		global $wpdb;

		if ( '' === $search || is_admin() || ! $query->is_main_query() || ! $query->is_search() ) {
			return $search;
		}

		$terms = (array) $query->get( 'search_terms' );
		if ( count( $terms ) < 2 ) {
			return $search; // 1語なら標準の検索のまま
		}

		$conditions = array();
		foreach ( $terms as $term ) {
			if ( str_starts_with( $term, '-' ) ) {
				return $search; // 「-語」の除外指定があるときは標準の検索に任せる
			}
			$like         = '%' . $wpdb->esc_like( $term ) . '%';
			$conditions[] = $wpdb->prepare(
				"({$wpdb->posts}.post_title LIKE %s OR {$wpdb->posts}.post_excerpt LIKE %s OR {$wpdb->posts}.post_content LIKE %s)",
				$like,
				$like,
				$like
			);
		}

		$search = ' AND (' . implode( ' OR ', $conditions ) . ') ';

		// 標準の検索と同じく、ログインしていない訪問者にはパスワード保護の投稿を出さない
		if ( ! is_user_logged_in() ) {
			$search .= " AND ({$wpdb->posts}.post_password = '') ";
		}

		return $search;
	},
	10,
	2
);

search_terms は、WordPressがスペースで区切ったあとの語の配列です。自分で explode() するより、WordPressと同じ区切り方(" で囲んだ語句の扱いなど)になります。OR検索にすると結果の件数は増えるので、検索結果ページの並び順や件数表示もあわせて確認してください。

MySQLのngram全文検索に切り替える

記事数が多く検索が遅い場合は、MySQLの全文検索(FULLTEXTインデックス)とngramパーサーを使う方法があります。ngramパーサーは、文章を2文字ずつ(既定値)に区切って索引を作るため、単語の区切りがない日本語でも全文検索ができます。

使える環境か確認する

  • MySQL 5.7.6以降が必要です(InnoDBのngramパーサー)。
  • MariaDBでは使えません。MariaDB 11.8で WITH PARSER ngram を指定すると、Function 'ngram' is not defined というエラーになりました。
  • インデックスを作るには、テーブルを変更する権限(ALTER)が必要です。
wp db query "SELECT VERSION();"

表示に MariaDB が含まれる場合、この節の方法は使えません。前の節までの方法で改善してください。

FULLTEXTインデックスを作る

作業前にデータベースのバックアップを取ります。初回はテーブルの再構築が行われるため、記事数が多いサイトでは時間がかかります。アクセスの少ない時間帯に実行してください。

wp db export before-fulltext.sql

wp db query "SET SESSION sql_mode = REPLACE(REPLACE(@@SESSION.sql_mode, 'NO_ZERO_IN_DATE', ''), 'NO_ZERO_DATE', ''); ALTER TABLE $(wp db prefix)posts ADD FULLTEXT INDEX ft_title_content (post_title, post_content) WITH PARSER ngram;"

1行目の SET SESSION sql_mode は、MySQL 8.0以降の既定の設定で ALTER TABLE が Invalid default value for 'post_date' というエラーになるのを避けるためのものです(wp_posts の日付の列が、既定値として 0000-00-00 00:00:00 を使っているため)。変更はこの接続の間だけ有効です。

元に戻すときは、インデックスを削除します。

wp db query "ALTER TABLE $(wp db prefix)posts DROP INDEX ft_title_content;"

検索条件をMATCH ... AGAINSTに置き換える

インデックスを作ってから、次のコードを有効にします。インデックスがない状態で有効にすると、Can't find FULLTEXT index matching the column list というエラーで検索結果が空になります。

<?php
/**
 * Plugin Name: ngram全文検索に切り替える
 * 前提: wp_posts に (post_title, post_content) の FULLTEXT インデックス(WITH PARSER ngram)があること
 */

add_filter(
	'posts_search',
	function ( $search, $query ) {
		global $wpdb;

		if ( '' === $search || is_admin() || ! $query->is_main_query() || ! $query->is_search() ) {
			return $search;
		}

		$parts = array();
		foreach ( (array) $query->get( 'search_terms' ) as $term ) {
			$exclude = str_starts_with( $term, '-' );
			$word    = str_replace( '"', '', $exclude ? substr( $term, 1 ) : $term );

			// ngram_token_size(既定2)より短い語は全文検索で探せないため、標準の検索に任せる
			if ( mb_strlen( $word ) < 2 ) {
				return $search;
			}
			$parts[] = ( $exclude ? '-' : '+' ) . '"' . $word . '"';
		}

		if ( ! preg_grep( '/^\+/', $parts ) ) {
			return $search; // 除外語だけの検索は標準の検索に任せる
		}

		$search = $wpdb->prepare(
			" AND MATCH({$wpdb->posts}.post_title, {$wpdb->posts}.post_content) AGAINST (%s IN BOOLEAN MODE) ",
			implode( ' ', $parts )
		);

		// 標準の検索と同じく、ログインしていない訪問者にはパスワード保護の投稿を出さない
		if ( ! is_user_logged_in() ) {
			$search .= " AND ({$wpdb->posts}.post_password = '') ";
		}

		return $search;
	},
	10,
	2
);

このコードは、各語を +"語"(含むことが条件の語句)、除外語を -"語" に変換して、ブーリアンモードで検索します。手元の検証では、次のような結果になりました。

  • 「設定方法」: 「設定方法」を連続して含む記事だけがヒット(自然言語モードで検索すると、「方法論」のように「方法」を含むだけの記事まで出てしまう)
  • 「設定 -メール」: 「設定」を含み「メール」を含まない記事がヒット
  • 「猫」(1文字): 全文検索では探せないため、標準の LIKE 検索に切り替わる
  • ログインしていない状態では、パスワード保護の投稿は出ない

MATCH() に指定する列は、インデックスを作ったときの列(post_title, post_content)と同じ組み合わせにする必要があります。抜粋(post_excerpt)も対象にしたい場合は、インデックスの列にも加えてください。

ngram_token_sizeを変える場合

1文字の語も全文検索で探したい場合は、MySQLの設定ファイル(my.cnf など)で ngram_token_size を1にします。この値は実行中に変更できない(read only)ため、設定後にMySQLの再起動と、インデックスの削除・再作成が必要です。

[mysqld]
ngram_token_size = 1

1にすると索引が大きくなり、2文字以上の語でも一致する記事が増えます。レンタルサーバーなどMySQLの設定を変えられない環境では、既定の2のまま、前述のコードのように1文字の語だけ標準の検索に任せる方法が現実的です。全文検索の仕組みをさらに詳しく知りたい場合は、WordPressでFULLTEXTインデックスを使った検索を実装する方法も参考にしてください。

検索プラグインを使う場合

独自の索引を作る検索プラグインを使う方法もあります。ただし、多くの検索プラグインは空白で単語を区切る英語向けの仕組みを前提にしているため、導入前に日本語の記事で実際に検索して、期待どおりにヒットするか確かめてください。

有料プラグインのSearchWPは、WordPress.orgのプラグインディレクトリにはないため、wp plugin install searchwp のようにスラッグでは入れられません。購入後にダウンロードしたZIPファイルを、「プラグイン」→「新規プラグインを追加」→「プラグインのアップロード」から入れるか、WP-CLIでファイルを指定して入れます。

wp plugin install ./searchwp.zip --activate

検索対象の列を絞る

WordPress 6.2以降では、post_search_columns フィルターで検索対象の列を絞れます。タイトルだけを検索したい場合などに使えます。

<?php
add_filter(
	'post_search_columns',
	function ( $search_columns, $search, $query ) {
		if ( ! is_admin() && $query->is_main_query() ) {
			return array( 'post_title' );
		}
		return $search_columns;
	},
	10,
	3
);

指定できる列は post_title、post_excerpt、post_content の3つです。

まとめ

  • WordPressの標準検索は LIKE '%語%' による部分一致で、日本語でも動く。ヒットしない主な原因は、表記の違い・全角スペース・半角カナ・照合順序
  • ひらがなとカタカナ、全角と半角の英字を同じとみなすかは照合順序で決まる。utf8mb4_unicode_520_ci などは同じとみなし、utf8mb4_general_ci は区別する
  • 検索語の正規化は mb_convert_kana() の sKV が安全。H は半角カタカナをひらがなにするオプションで、カタカナ全般の変換ではない
  • 検索条件の変更は posts_search で行う。posts_where を丸ごと置き換えると、下書きや非公開の投稿まで出てしまう
  • 記事が多く遅い場合は、MySQL 5.7.6以降のngram全文検索が使える。MariaDBでは使えない。インデックス作成前にバックアップを取る
  • SearchWPは有料で、wp plugin install のスラッグ指定では入れられない。どのプラグインも、日本語の記事で試してから導入する

お気軽にご相談ください

お見積りへ お問い合わせへ
▲