Table of contents :

Searching Across Multiple Product Fields

100-days-of-elasticsearch-woocommerce-019

Table of contents :

Product relevance often depends on information distributed across several fields. A shopper may enter a brand, model number, product type, and descriptive phrase in one query, while the indexed product stores those values in separate fields such as name, sku, brand, categories, and description.

For WooCommerce agencies, the important decision is not simply which fields to search. It is how Elasticsearch should combine matches, how strongly each field should influence ranking, and how the query should behave when a term appears in different fields.

Typical product fields

A WooCommerce product index might expose fields similar to these:

  • name: the product title, usually mapped as analyzed text with a keyword subfield.
  • sku: an exact or partially searchable stock keeping unit.
  • brand: a brand name, often available as both text and keyword data.
  • categories: category names or category paths.
  • short_description and description: longer product content.
  • attributes.*: values such as color, size, material, or compatibility.

The final field names depend on the indexing plugin or custom synchronization layer. Always inspect the index mapping and use the actual field names rather than assuming that WooCommerce database columns map directly to Elasticsearch fields.

Use multi_match for related text fields

The multi_match query is a convenient starting point when the same user-entered text should be tested against several fields.

{
  "query": {
    "multi_match": {
      "query": "wireless noise cancelling headphones",
      "fields": [
        "name^5",
        "brand^3",
        "categories^2",
        "short_description",
        "description"
      ],
      "type": "best_fields",
      "operator": "and"
    }
  }
}

In this example, a match in the product name receives more influence than a match in the long description. The ^ notation applies a field boost; it does not alter the underlying field mapping.

The best_fields type is useful when a product should rank highly because one field contains a strong, coherent match. It is often appropriate for product names and descriptions, but it can be too strict when a shopper’s terms are naturally distributed across fields.

Choosing the multi-field matching strategy

best_fields

best_fields scores the best matching field, with an optional contribution from the other matching fields. This works well when the product title is the primary relevance signal.

{
  "query": {
    "multi_match": {
      "query": "cotton summer shirt",
      "fields": ["name^5", "short_description^2", "description"],
      "type": "best_fields",
      "tie_breaker": 0.2
    }
  }
}

The tie_breaker value allows other matching fields to contribute without allowing repeated words in every field to dominate the score.

most_fields

most_fields adds the scores from matching fields. It is useful when the same product content is indexed in several analyzed forms, such as a standard field and a stemmed or synonym-aware field.

{
  "query": {
    "multi_match": {
      "query": "running shoes",
      "fields": [
        "name^4",
        "name.stemmed^3",
        "description",
        "description.stemmed"
      ],
      "type": "most_fields"
    }
  }
}

Use this type carefully with duplicated product content. If the same text is copied into many independent fields, products can receive an inflated score simply because the content was duplicated.

cross_fields

cross_fields treats several fields as though they were one combined field. This is helpful when a query contains separate concepts that may be stored in different places.

{
  "query": {
    "multi_match": {
      "query": "acme waterproof jacket",
      "fields": ["brand^3", "name^5", "categories^2"],
      "type": "cross_fields",
      "operator": "and"
    }
  }
}

This can match acme in the brand field and waterproof jacket in the product name while requiring all terms to be present across the selected fields. The fields should use compatible analyzers. Mixing fields with substantially different analysis rules can produce surprising term grouping and scoring.

Combine field-specific logic with a Boolean query

Real catalog search usually needs different behavior for different field types. A SKU should not be treated exactly like a long description, and an exact brand match may deserve a separate ranking signal.

{
  "query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "query": "oak desk",
            "fields": ["name^5", "categories^2", "description"],
            "type": "best_fields",
            "operator": "and"
          }
        }
      ],
      "should": [
        {
          "term": {
            "sku.keyword": {
              "value": "oak-desk",
              "boost": 12
            }
          }
        },
        {
          "term": {
            "brand.keyword": {
              "value": "example-brand",
              "boost": 4
            }
          }
        }
      ],
      "minimum_should_match": 0
    }
  }
}

Use must for conditions that determine whether a product is eligible. Use should for optional relevance signals. A filter such as stock status, catalog visibility, or product type should normally be placed in filter so it restricts results without affecting relevance scoring.

{
  "query": {
    "bool": {
      "filter": [
        { "term": { "stock_status": "instock" } },
        { "term": { "catalog_visibility": "visible" } }
      ],
      "must": [
        {
          "multi_match": {
            "query": "blue hiking backpack",
            "fields": ["name^5", "brand^3", "categories^2", "description"],
            "operator": "and"
          }
        }
      ]
    }
  }
}

Search SKUs without weakening natural-language search

SKUs frequently contain punctuation, digits, and meaningful prefixes. A single analyzed text field may not support both exact lookup and partial user input effectively. Index a keyword representation for exact matches and a separate text or edge-ngram representation for prefix-style search.

{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "sku.keyword": {
              "value": "AB-1234",
              "boost": 20
            }
          }
        },
        {
          "match": {
            "sku": {
              "query": "AB 1234",
              "boost": 8
            }
          }
        },
        {
          "multi_match": {
            "query": "AB 1234",
            "fields": ["name^5", "brand^3", "categories^2", "description"]
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}

Do not use a wildcard query across every product field as the default search strategy. Leading wildcards such as *1234 can be expensive, and wildcard matching does not provide the same linguistic relevance as an analyzed query. If partial SKU search is a requirement, configure an appropriate analyzer at index-creation time and reindex the catalog.

Handle product attributes deliberately

Attribute data may be stored as ordinary objects, flattened fields, or nested objects. If each attribute object contains a name and value that must belong to the same attribute, a nested mapping is usually required.

{
  "query": {
    "nested": {
      "path": "attributes",
      "query": {
        "bool": {
          "must": [
            { "match": { "attributes.name": "color" } },
            { "match": { "attributes.value": "blue" } }
          ]
        }
      }
    }
  }
}

Without a nested mapping, Elasticsearch can match the attribute name from one object and the attribute value from another object. That can produce false positives in products with several attributes. Confirm the mapping before building attribute-aware search logic.

Use minimum_should_match for forgiving queries

Requiring every term can be appropriate for identifiers and highly specific B2B catalogs, but it may hide useful products when shoppers enter long, imperfect phrases. A percentage rule provides a compromise.

{
  "query": {
    "multi_match": {
      "query": "black waterproof hiking backpack laptop",
      "fields": ["name^5", "brand^3", "categories^2", "description"],
      "type": "best_fields",
      "minimum_should_match": "75%"
    }
  }
}

Test this with real search logs. A permissive rule can increase recall while also admitting unrelated products, especially when the catalog contains common terms such as premium, new, or classic.

Production considerations for WooCommerce

  • Keep field boosts in application configuration so relevance can be adjusted without rewriting the integration.
  • Use filter clauses for stock, visibility, language, store, and permission constraints.
  • Prefer stable keyword fields for exact brand, SKU, product ID, and taxonomy identifiers.
  • Verify that translated fields use the intended language analyzer and are included in the query for the active storefront language.
  • Profile slow queries with the Elasticsearch Profile API and inspect representative results, not just query latency.
  • Test searches containing one term, multiple terms, an exact SKU, a brand plus model, a category plus attribute, and misspelled or incomplete input.

A practical agency workflow is to export anonymized search terms from the WooCommerce storefront, classify them by intent, and evaluate each query against expected products. This exposes whether a boost, analyzer, field type, or Boolean clause is responsible for poor results.

Trending posts
You might also like