2026年11月14日
2026年11月14日
Elasticsearch for WordPress Search: ElasticPress and Japanese Kuromoji
This article is a localized edition of the Japanese original. Read the Japanese original
WordPress's built-in site search uses LIKE in the database (MySQL or MariaDB) to check whether a post's title, excerpt or content contains the search terms. It tends to slow down as posts pile up, and results are not ordered by relevance. With the ElasticPress plugin, you can hand search over to the Elasticsearch full-text search engine.
The steps in this article were tested on WordPress 7.1, ElasticPress 5.3.5 and Elasticsearch 9.5.5 (Docker) as of November 2026.
Architecture and requirements
- An Elasticsearch server: Run your own (on a VPS or with Docker) or use ElasticPress.io, the hosted service from the plugin's developer. Shared hosting almost never lets you run Elasticsearch.
- The ElasticPress plugin: It replaces WordPress search queries (
WP_Query) with Elasticsearch queries. The official requirements are WordPress 6.2+, PHP 7.4+ and Elasticsearch 5.2+.
Once ElasticPress is installed, your posts are copied into an Elasticsearch index, and searches run against it. When you save or delete a post, ElasticPress updates the index automatically.
Start Elasticsearch (Docker, with the Japanese plugin)
To split Japanese text into words you need analysis-kuromoji, the official Elasticsearch plugin for Japanese morphological analysis. Build an image with the plugin included so it survives when the container is recreated. Put these two files in a working directory.
Dockerfile:
FROM elasticsearch:9.5.5
RUN bin/elasticsearch-plugin install --batch analysis-kuromoji
compose.yaml:
services:
elasticsearch:
build: .
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- ES_JAVA_OPTS=-Xms512m -Xmx512m
ports:
- "127.0.0.1:9200:9200"
volumes:
- es-data:/usr/share/elasticsearch/data
volumes:
es-data:
docker compose up -d --build
# Check that it started (green or yellow "status" means it is running)
curl -s "http://127.0.0.1:9200/_cluster/health?pretty"
# Check that kuromoji is installed
curl -s "http://127.0.0.1:9200/_cat/plugins"
This setup is for development and testing, used by WordPress on the same server.
xpack.security.enabled=falseturns off authentication and encryption, soportsis bound to127.0.0.1to block outside connections. Do not use this in a setup exposed to the internet.- In production, follow the official Elasticsearch documentation to enable authentication and HTTPS, and review memory (the heap size in
ES_JAVA_OPTS) and kernel settings (vm.max_map_count).
For installing Elasticsearch in general, see how to install Elasticsearch.
Install ElasticPress and sync
1. Install the plugin
Go to Plugins → Add Plugin, search for "ElasticPress", then install and activate it.
2. Set the connection
Add the host to wp-config.php (you can also enter it on the ElasticPress settings screen in the admin).
<?php
// wp-config.php (above the "That's all, stop editing!" line)
define( 'EP_HOST', 'http://127.0.0.1:9200/' );
// If Elasticsearch authentication is enabled, set the username and password
// define( 'ES_SHIELD', 'username:password' );
3. Sync your posts
Send your posts to Elasticsearch (sync). You can also run it from ElasticPress → Sync in the admin, but WP-CLI is more dependable on sites with many posts.
wp elasticpress status # Check the connection
wp elasticpress sync --setup --yes # Recreate the index and send everything
wp elasticpress list-features # Active features (search should be listed)
In our test it reported Number of posts indexed: 30, sending the published posts and pages. ElasticPress's Search feature (search) is on as soon as the plugin is activated, and front-end site search (?s=) is handled by Elasticsearch.
--setup deletes and recreates the index. Whenever you change the index settings (the mapping), as with the Japanese setup below, sync again with --setup. Changes take a moment to become searchable; in our test, searching immediately in the same process as the sync returned zero results.
Split Japanese into words (kuromoji)
ElasticPress picks Elasticsearch language settings to match the site language, but as of November 2026, ElasticPress 5.3.5 has no mapping for Japanese, so Japanese sites get the English settings (the standard tokenizer). The standard tokenizer splits kanji into single characters, so a search for 京都 (Kyoto) also finds posts containing 東京都 (Tokyo Metropolis).
Save the following file as wp-content/mu-plugins/ep-japanese.php to make the post index use kuromoji.
<?php
/**
* Plugin Name: ElasticPress Japanese analyzer
* Description: Use kuromoji (Japanese morphological analysis) for the ElasticPress post index.
*/
// Replace the post index's default analyzers with kuromoji
add_filter( 'ep_post_mapping', function ( $mapping ) {
$analyzer = array(
'type' => 'custom',
'char_filter' => array( 'html_strip' ),
'tokenizer' => 'kuromoji_tokenizer',
'filter' => array(
'kuromoji_baseform',
'kuromoji_part_of_speech',
'cjk_width',
'ja_stop',
'kuromoji_stemmer',
'lowercase',
),
);
$mapping['settings']['analysis']['analyzer']['default'] = $analyzer;
$mapping['settings']['analysis']['analyzer']['default_search'] = $analyzer;
return $mapping;
} );
Then sync again with wp elasticpress sync --setup --yes. To confirm the change, look up the index name and display its settings (if the default analyzer shows kuromoji_tokenizer, it is in effect).
wp elasticpress get-indices
# Pass the index name it shows (for example, example-com-post-1)
wp elasticpress get-index-settings example-com-post-1 --pretty
Here is what we found, comparing five Japanese posts.
| Search term | Standard tokenizer | kuromoji |
|---|---|---|
京都 (Kyoto) |
2 posts: the Kyoto sightseeing post and a post containing 東京都 (Tokyo) |
1 post: the Kyoto sightseeing post |
速い (fast) |
1 post: the one containing 高速化 (speed-up) |
2 posts: it also found the one containing 速くなります (becomes faster) |
kuromoji treats the inflected form 速く as its base form 速い, so conjugated forms are found too. On the other hand, strings inside a word (such as 京都 within 東京都) no longer match. Which behavior suits you depends on your content, so test with your real posts before deciding.
Exclude specific posts from search
By default ElasticPress only sends published (publish) posts, so you need nothing extra to keep drafts or private posts out. To exclude other posts, for example ones flagged with a custom field, exclude them both in the full sync and in the sync that runs when a post is saved.
<?php
// In the full sync (wp elasticpress sync), skip posts where _myprefix_exclude_search is 1
add_filter( 'ep_post_query_db_args', function ( $args ) {
$args['meta_query'] = array(
'relation' => 'OR',
array(
'key' => '_myprefix_exclude_search',
'compare' => 'NOT EXISTS',
),
array(
'key' => '_myprefix_exclude_search',
'value' => '1',
'compare' => '!=',
),
);
return $args;
} );
// Also skip the same posts when they are saved
add_filter( 'ep_post_sync_kill', function ( $skip, $post_id ) {
if ( '1' === get_post_meta( $post_id, '_myprefix_exclude_search', true ) ) {
return true;
}
return $skip;
}, 10, 2 );
In our test, a post with this field was left out of the sync and did not appear in results even though its content contained the search term. Note that ep_post_sync_kill only stops sending; if you add the field to a post that is already indexed, sync again with wp elasticpress sync --setup --yes.
Set up filters and weighting in the admin
ElasticPress has built-in features for filtering results and tuning their order. Use these before writing your own queries.
- Filtering (the Filters feature): It is on by default and provides blocks such as "Filter by Taxonomy", "Filter by Post Type", "Filter by Metadata" and "Filter by Post Date". Place them in search result or archive templates to let visitors narrow results by category, tag and so on.
- Weighting: Under ElasticPress → Search Fields & Weighting, choose which of the title, content, excerpt, taxonomies and other fields are searched and how much each counts. "Add field" lets you add a custom field (Metadata key) to the search.
Troubleshooting
wp elasticpress statusfails: Check theEP_HOSTURL (http/https, port, trailing/) and whether the WordPress server can reach Elasticsearch (doescurlget a response from/_cluster/health?).- Search results do not change: Check that
wp elasticpress list-featureslistssearchand that the sync has finished. - The Japanese settings have no effect: Check that you synced again with
--setupafter addingep-japanese.php, and that analysis-kuromoji is installed in Elasticsearch (/_cat/plugins).
Related articles
- Designing Elasticsearch indexes and mappings
- Fixing Japanese text that WordPress search fails to find
- How to customize WordPress search results
Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)