Skip to main content
net10.0

Umbraco Commerce Search provides order indexing and querying via Umbraco.Cms.Search abstractions.

Published
Jul 16, 2026
3mo ago
Total Downloads
251
251

Install

dotnet add package Umbraco.Commerce.Search --version 18.0.0-beta.1
ProductVersions
.NET
net10.0

README

Umbraco.Commerce.Search

A drop-in replacement that makes Umbraco Commerce's product and store search run on the Umbraco.Cms.Search abstractions instead of directly against Examine.

Adding the package swaps Commerce's Examine-backed IProductAdapter and store finder for Cms.Search-backed implementations β€” product lookup, catalogue search, category extraction and store resolution behave the same, but are served through IIndexer / ISearcher (with Examine as one provider behind them). It is the first step in migrating Commerce off its direct Examine coupling.

Compatible with Umbraco CMS 18 and Umbraco Commerce 18. For CMS / Commerce 17, use the support/17.x branch.

Installation

Register the search core, the Examine provider, Umbraco Commerce, and then this package:

builder.CreateUmbracoBuilder()
    .AddBackOffice()
    .AddWebsite()
    .AddDeliveryApi()
    .AddSearchCore()                 // Umbraco.Cms.Search.Core
    .AddExamineSearchProvider()      // Umbraco.Cms.Search.Provider.Examine
    .AddComposers()
    .AddUmbracoCommerce()
    .AddUmbracoCommerceSearch()      // must come after AddUmbracoCommerce so it can override its services
    .Build();

How it works

AddUmbracoCommerceSearch() does four things:

  1. Enriches content documents β€” registers a CommerceContentIndexer (IContentIndexer) that adds Commerce-specific fields to product and store content nodes as they're indexed into the built-in content indexes (both draft and published). This replaces Commerce's legacy TransformingIndexValues / UmbracoCommerceVariantsEditorExamineValueOptimizer hook. The fields (prefixed so they never collide with the built-in property-value indexer) are:

    Field Type Source
    umbracoCommerceStore keyword store-picker value on store-root nodes
    umbracoCommerceIsProduct keyword "true" on nodes with a sku or variants property
    umbracoCommerceSku keyword the product's own SKU
    umbracoCommerceVariantSkus keyword[] SKUs parsed from the Variants Editor value
    umbracoCommerceCategories keyword[] (facetable) category references
    umbracoCommerceProductSource keyword product-source reference
    umbracoCommerceSearchText text SKU + product name, for free-text matching
  2. Declares those non-textual fields in FieldOptions so the Examine provider indexes them as filterable / facetable. Without this, keyword filters silently return nothing.

  3. Replaces the product adapter β€” AddUnique<IProductAdapter, CmsSearchProductAdapter>(). CmsSearchProductAdapter subclasses Commerce's UmbracoProductAdapter, inheriting all non-search behaviour (product snapshots, variant attributes) unchanged and overriding only the three methods that used Examine:

    • TryGetProductReferenceAsync β€” SKU β†’ product/variant reference (draft index).
    • SearchProductSummariesAsync β€” paged catalogue search (published index).
    • GetProductCategoriesAsync β€” distinct categories via a facet (published index).
  4. Replaces the store finder β€” swaps UmbracoLuceneStoreFinder for CmsSearchStoreFinder in the store finder collection (the two cache-based finders are left in place). It walks a node's ancestors via the content cache to find the nearest store, with a product-source fallback.

Index choice

Capability Index
Catalogue search, category extraction Umb_PublishedContent
SKU lookup, store resolution Umb_Content (draft / all content)

This mirrors the legacy behaviour: catalogue search returned published products only, while SKU lookup and store resolution worked against all content (the Examine InternalIndex).

Reindexing after install (important)

Umbraco.Cms.Search persists collected fields in a database table (umbracoIndexDocument) and treats it as the source of truth β€” the Examine indexes are just a projection of it. A rebuild (the backoffice button or PUT /umbraco/search/api/v1/rebuild?indexAlias=<alias>) only resets Examine and re-projects that stored table; it does not re-run the content indexers for content that already has a stored document. So adding this package to a site whose content was already indexed by Cms.Search before the package was installed will not surface the umbracoCommerce* fields β€” a rebuild alone is not enough, and product search will silently return nothing.

To pick up the new fields on an existing site, force a fresh collection so the indexers run again:

  • Republish the affected content (publishing deletes the stored document, so the next index pass re-collects through all indexers), or
  • Clear umbracoIndexDocument (e.g. DELETE FROM umbracoIndexDocument) and then rebuild both content indexes β€” the backoffice button, or PUT /umbraco/search/api/v1/rebuild?indexAlias=Umb_PublishedContent and PUT /umbraco/search/api/v1/rebuild?indexAlias=Umb_Content. Note indexAlias is a query parameter, not a request-body field.

On a fresh site where the package is present before content is first indexed, this does not apply β€” the Commerce fields are collected from the start.

Limitations

  • Product-source scoping β€” catalogue search and category extraction scope to a store by the store-root ancestor (Umb_PathIds). Products linked into a store from elsewhere via a productSource relation are not yet included in those results (Cms.Search search hits expose only document ids, not field values, so the source reference can't be read back from a result without rehydration). Store resolution still honours productSource because it reads the node directly. Tracked as a follow-up.
  • Product summaries are built from the public IPublishedContent.Value<T>() API rather than Commerce's internal PublishedContentHelper (which isn't accessible from this package), so recursive property resolution differs slightly from the in-product adapter.
  • Unpublished nodes that aren't in the published cache fall through to Commerce's content-service store finder, as before.
  • Unit tests mock ISearcher / IContentBase, so they verify field projection and query composition, not real provider behaviour. End-to-end search is only proven against a running Examine index β€” use the demo (setup-demo.ps1).

Project layout

src/Umbraco.Commerce.Search/
β”œβ”€β”€ Constants.cs                              // Names of the injected content fields
β”œβ”€β”€ Extensions/UmbracoBuilderExtensions.cs    // AddUmbracoCommerceSearch()
β”œβ”€β”€ Adapters/CmsSearchProductAdapter.cs       // IProductAdapter override (search methods)
β”œβ”€β”€ Finders/CmsSearchStoreFinder.cs           // IUmbracoNodeStoreFinder (replaces the Lucene finder)
└── Services/
    β”œβ”€β”€ CommerceContentIndexer.cs             // IContentIndexer β€” enriches content docs
    β”œβ”€β”€ ICommerceContentSearcher.cs           // Query surface over the content indexes
    └── CommerceContentSearcher.cs            // ISearcher-backed implementation

See docs/superpowers/specs/2026-06-30-commerce-search-examine-replacement-design.md for the full design.

Running the demo

The demo is not committed. To scaffold one locally:

./setup-demo.ps1

This clones the official Umbraco Commerce demo store, installs Umbraco.Cms.Search.Core + Umbraco.Cms.Search.Provider.Examine and a project reference to the local Umbraco.Commerce.Search, patches Program.cs to call .AddSearchCore() / .AddExamineSearchProvider() / .AddUmbracoCommerceSearch(), and generates a git-ignored Umbraco.Commerce.Search.local.slnx. Run ./setup-demo.ps1 -? for parameters.

Changes from Previous Version

No structural changes between v18.0.0--beta.1.preview.2.gfb00115 and v18.0.0-beta.1.

Adoption Assessment

A verified publisher signal is available. Assess fit from the package's supported frameworks, license and dependency graph rather than popularity alone.

This version is marked prerelease. Validate its API and upgrade path before production use.No SPDX license expression is published. Review the license text and your organisation's policy before redistribution.Compatibility metadata lists 1 target framework; confirm the exact target used by your application.

Related Guides & Workflows

Learn how to evaluate, integrate, or audit this package in your .NET project.