WooCommerce product search often starts with a simple keyword query, but a match query provides much better control over how Elasticsearch interprets customer input. It analyzes the search text, converts it into terms using the field’s analyzer, and finds documents that contain matching terms rather than requiring an exact field-value match.
Why use a match query for WooCommerce?
Product titles, descriptions, SKUs, and attributes are usually indexed as analyzed text. A customer may search for waterproof hiking boots, while the indexed product title contains Men’s Waterproof Boots for Hiking. A match query can analyze both the indexed content and the search input so that relevant products are returned even when the word order differs.
By comparison, a term query is intended for exact, un analyzed values. It is useful for fields such as a product ID, stock status, or a keyword field, but it is usually the wrong choice for natural-language product searches.
A basic match query
The following query searches a product title field for the terms entered by the shopper:
{
"query": {
"match": {
"title": "waterproof hiking boots"
}
}
}
With the default OR operator, Elasticsearch can return products matching one or more analyzed terms. This is flexible, but it may produce broad results. For example, a product containing only boots could match the query even though it does not contain waterproof or hiking.
Requiring all search terms
For product search, requiring every meaningful term is often a better default. Set the operator to and when a product should contain all analyzed terms:
{
"query": {
"match": {
"title": {
"query": "waterproof hiking boots",
"operator": "and"
}
}
}
}
This improves precision, but it can be too strict when customers misspell words or when a product title uses a close synonym. A common WooCommerce implementation combines an exact multi-term match with a more tolerant query and assigns different relevance boosts.
Controlling relevance with minimum_should_match
The minimum_should_match option provides more flexibility than choosing only OR or AND. It allows a product to match most of the search terms while avoiding results that contain only one weakly related word.
{
"query": {
"match": {
"description": {
"query": "organic cotton summer shirt",
"minimum_should_match": "75%"
}
}
}
}
For a four-term query, 75% requires at least three terms to match. The appropriate threshold depends on the length of typical WooCommerce searches. A percentage that works well for four or five terms may be too restrictive for two-term searches, so test it against real search logs.
Using match_phrase for ordered phrases
A regular match query does not require words to appear next to each other or in the same order. Use match_phrase when the phrase itself is important, such as a product name, material, or model description:
{
"query": {
"match_phrase": {
"title": {
"query": "stainless steel bottle",
"slop": 1
}
}
}
}
The slop value allows a limited number of positional gaps between terms. A value of 1 can match a title such as stainless insulated steel bottle, depending on the analyzer and token positions. Phrase matching is useful as a boosted clause, but it should not always replace a normal match query because customers may enter terms in a different order.
Searching multiple WooCommerce fields
Most stores need to search more than the product title. A multi_match query can search titles, descriptions, short descriptions, SKUs, and indexed attributes while giving each field a different importance.
{
"query": {
"multi_match": {
"query": "blue running shoes",
"fields": [
"title^5",
"sku^4",
"short_description^2",
"description",
"attributes.name^2",
"attributes.value^2"
],
"type": "best_fields",
"operator": "and"
}
}
}
The caret notation applies a relevance boost. A title match should normally rank higher than a description-only match, while a SKU match may deserve a strong boost when customers frequently search by catalog code. The field names must match the actual Elasticsearch mapping used by the WooCommerce indexing process.
Combining exact, phrase, and tolerant matching
A practical search request often uses a bool query. Exact keyword fields, phrase matches, and regular analyzed matches can be placed in should clauses so that stronger matches receive higher scores:
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "wireless noise cancelling headphones",
"fields": [
"title^5",
"short_description^2",
"description"
],
"minimum_should_match": "75%"
}
}
],
"should": [
{
"multi_match": {
"query": "wireless noise cancelling headphones",
"type": "phrase",
"fields": ["title^8", "short_description^3"]
}
},
{
"term": {
"sku.keyword": {
"value": "WH-1000XM5",
"boost": 10
}
}
}
],
"filter": [
{
"term": {
"status": "publish"
}
}
]
}
}
}
Use filter for constraints that should not affect relevance, such as published status, catalog visibility, stock state, or a selected product category. Use must and should for clauses that should contribute to the score.
Handling spelling mistakes with fuzziness
Customers regularly enter searches such as runing shoes or bluetooh speaker. A match query can enable fuzzy matching:
{
"query": {
"match": {
"title": {
"query": "bluetooh speaker",
"fuzziness": "AUTO",
"prefix_length": 2
}
}
}
}
Fuzziness can improve recall, but applying it broadly to long descriptions or every field may increase query cost and produce irrelevant results. It is generally safer to use it as a lower-boost fallback after an exact or phrase-oriented clause. The prefix_length setting protects the beginning of a term from edits and can reduce the number of fuzzy expansions.
Analyzer and mapping considerations
A match query depends on the analyzer configured for the target field. Lowercasing, stemming, stop-word removal, synonyms, and language-specific tokenization all affect the terms that can match. If a WooCommerce store needs searches for phrases such as trainer and sneaker to be related, configure synonyms at index and search time rather than trying to solve the problem only in the query.
Keep exact and analyzed values available as separate multi-fields where appropriate:
<code{
"mappings": {
"properties": {
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"sku": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 100
}
}
}
}
}
}
The analyzed title field is appropriate for natural-language matching, while title.keyword can support exact sorting, aggregations, or exact-value checks. SKU behavior should be validated with the store’s actual catalog format because hyphens, spaces, and letters may require a custom analyzer or a normalized keyword field.
Implementation guidance for WooCommerce agencies
- Inspect the index mapping before writing queries. Confirm whether product titles, SKUs, attributes, and taxonomy labels are mapped as
text,keyword, or nested objects. - Use a title boost and phrase boost to prioritize products whose names closely match the shopper’s query.
- Keep availability, publication, catalog visibility, language, and store filters in
filterclauses. - Use
minimum_should_matchoroperator: andto control overly broad results, then add a lower-priority fuzzy fallback for misspellings. - Test short queries, SKU searches, attribute searches, plural forms, stop words, misspellings, and searches containing hyphens or model numbers.
- Measure zero-result rate, click-through rate, add-to-cart rate, and conversion rate by query. Relevance changes should be validated against actual shopper behavior.
Example request from a WooCommerce search endpoint
An application can send the shopper’s search term to an endpoint that builds the Elasticsearch request server-side. Do not accept arbitrary query JSON from the browser. The server should validate the input, apply the store’s mandatory filters, and enforce pagination limits.
POST /products/_search
{
"from": 0,
"size": 24,
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "waterproof hiking boots",
"fields": ["title^5", "short_description^2", "description"],
"type": "best_fields",
"minimum_should_match": "75%"
}
}
],
"should": [
{
"multi_match": {
"query": "waterproof hiking boots",
"type": "phrase",
"fields": ["title^8", "short_description^3"]
}
}
],
"filter": [
{ "term": { "status": "publish" } },
{ "term": { "catalog_visibility": "visible" } }
]
}
},
"sort": ["_score", "_id"]
}
A deterministic secondary sort such as _id helps keep pagination stable when multiple products have the same score. For larger catalogs or deep pagination, consider point-in-time searches with search_after rather than increasing from indefinitely.