For WooCommerce search features, an exact match is often different from a relevant text match. A shopper searching for SKU TSHIRT-BLU-M should not receive products whose descriptions merely contain similar words. Elasticsearch’s term query is designed for this type of lookup, provided that the target field is mapped as a keyword or another non-analyzed field.
What a term query does
A term query looks for the exact indexed term supplied in the query. Elasticsearch does not analyze, stem, tokenize, or otherwise process the value in the same way that it does for a typical match query.
{"query":{"term":{"sku.keyword":{"value":"TSHIRT-BLU-M"}}}}
This query is appropriate when sku.keyword contains the complete SKU as one indexed value. It will not match a different SKU such as TSHIRT-BLU-L, and it may not match a differently cased value unless the field has a suitable normalizer or the query uses supported case-insensitive behavior.
Use keyword fields for WooCommerce identifiers
WooCommerce agencies commonly need exact lookups for SKUs, product IDs, variation IDs, external ERP references, barcodes, and stock codes. These values should generally be indexed as keyword fields.
{"mappings":{"properties":{"sku":{"type":"keyword"},"product_id":{"type":"keyword"},"variation_id":{"type":"keyword"},"barcode":{"type":"keyword"}}}}
The exact mapping depends on the Elasticsearch integration used by the store. Do not assume that a field named sku has a particular type. Inspect the live index mapping before implementing a query:
GET woocommerce-products-*/_mapping
Some integrations map a text field with a keyword subfield, such as sku and sku.keyword. Others expose a dedicated keyword field or store the WooCommerce value under a plugin-specific path. Query the field that is actually mapped as keyword.
Term versus match for product data
A match query is intended for analyzed text, such as product titles and descriptions. A term query is intended for exact values.
{"query":{"match":{"name":"blue cotton shirt"}}}
{"query":{"term":{"sku.keyword":"TSHIRT-BLU-M"}}}
Using a term query against an analyzed text field can produce unexpected results. For example, a product title may be split into several indexed terms, while an SKU containing punctuation may be normalized or tokenized. If exact matching is required for a text value, add a keyword multi-field during index design and reindex existing products.
Filtering exact WooCommerce matches
Exact identifiers are usually filters rather than relevance signals. A bool.filter clause avoids scoring overhead and combines cleanly with storefront constraints such as catalog visibility, stock status, language, and product type.
{"query":{"bool":{"filter":[{"term":{"sku.keyword":{"value":"TSHIRT-BLU-M"}}},{"term":{"catalog_visibility.keyword":"visible"}},{"term":{"stock_status.keyword":"instock"}}]}}}
Field names such as catalog_visibility and stock_status vary between WooCommerce indexing solutions. Map the query to the fields exposed by the store’s index, and ensure that hidden, private, or out-of-stock products are not accidentally returned.
Matching several exact values
When an agency needs to retrieve a known set of products, use a terms query rather than creating many separate term clauses.
{"query":{"terms":{"sku.keyword":["TSHIRT-BLU-M","TSHIRT-BLU-L","TSHIRT-RED-M"]}}}
This is useful for ERP synchronization screens, bulk administration tools, cart validation, and APIs that receive a list of SKUs. Keep the list bounded and validate input before sending it to Elasticsearch. Very large lists may require the terms lookup mechanism or a different synchronization design.
Case sensitivity and normalization
Keyword values are normally matched exactly, including case. If the business treats SKUs as case-insensitive, define a lowercase normalizer on the keyword field and lowercase both indexed values and query input.
{"settings":{"analysis":{"normalizer":{"sku_normalizer":{"type":"custom","filter":["lowercase"]}}}},"mappings":{"properties":{"sku":{"type":"keyword","normalizer":"sku_normalizer"}}}}
Changing a mapping or normalizer requires a new index and reindexing. On Elasticsearch versions that support it, a term query can also use case_insensitive, but this should be treated as a query-level compatibility choice rather than a replacement for a consistent index design.
{"query":{"term":{"sku.keyword":{"value":"tshirt-blu-m","case_insensitive":true}}}}
Exact product and variation identifiers
WooCommerce products and variations often need separate handling. A parent product ID should not be confused with a variation ID, especially when pricing, stock, or add-to-cart behavior depends on the selected variation.
{"query":{"bool":{"should":[{"term":{"product_id.keyword":"4821"}},{"term":{"variation_id.keyword":"9274"}}],"minimum_should_match":1}}}
If a product document contains nested variation objects, use a nested query when the exact fields must belong to the same variation. Without a nested mapping, Elasticsearch may combine values from different array objects and return a false positive.
{"query":{"nested":{"path":"variations","query":{"bool":{"filter":[{"term":{"variations.sku.keyword":"TSHIRT-BLU-M"}},{"term":{"variations.stock_status.keyword":"instock"}}]}}}}}
Testing an exact-match implementation
- Inspect the index mapping and confirm that the selected field is a keyword field.
- Test the exact stored value, including punctuation, whitespace rules, and letter case.
- Test a near match, such as a different size or an SKU with an added suffix, and confirm that it is rejected.
- Verify parent-product and variation behavior with real WooCommerce fixtures.
- Check catalog visibility, language, stock, and permission filters before exposing the result through a storefront endpoint.
- Reindex after changing analyzers, normalizers, or field mappings.
For debugging, request the mapped field and indexed document through a non-public administrative tool, and log the normalized query value rather than relying on the display value shown in the WooCommerce interface.