search-algolia
Algolia as the search provider for an Evolve shop. It has two parts that
deploy separately. The index adapter writes the catalog into Algolia, and the
query adapter answers product search from it, with facets, sorting and
Algolia's personalization. Both plug into @evolve-framework/search, so the
indexing and the storefront's queries work the same as with any other provider.
When to use
- A shop's product search and product listings come from Algolia. Category
search is not implemented here yet, and the adapter reports it as
unsupported. The commercetools
CatalogModulethen answers category search from commercetools itself. - An indexer service keeps Algolia in step with commercetools or another
catalog: give its
SearchIndexerModuleanAlgoliaIndexAdapter. - You are moving off
@evolve-framework/commercetools/algolia, which this package replaces. The stored record shape is unchanged, so moving needs no reindex.
Get started
Install the package with the peer dependencies it needs. It comes from the Evolve registry, which needs a one-time sign-in.
pnpm add @evolve-framework/search-algolia @evolve-framework/core @evolve-framework/searchRequirements3
@evolve-framework/core>= 1.0.0 < 2.0.0@evolve-framework/search>= 0.2.0 < 2.0.0@types/node>=22optional
For example:
import { AlgoliaIndexAdapter } from "@evolve-framework/search-algolia/indexing";import { AlgoliaQueryAdapter } from "@evolve-framework/search-algolia/query";
const appId = process.env.ALGOLIA_APP_ID ?? "";
// The indexer writes, so it holds the write key.export const indexAdapter = new AlgoliaIndexAdapter({ appId, writeApiKey: process.env.ALGOLIA_WRITE_API_KEY ?? "",});
// The service answering product search only reads, with a search-only key.export const queryAdapter = new AlgoliaQueryAdapter({ appId, searchApiKey: process.env.ALGOLIA_SEARCH_API_KEY ?? "",});Adapters
AlgoliaIndexAdapter
Writes documents to Algolia.
Every method throws on failure rather than logging and returning: a swallowed error acks the queue message that triggered the write, losing the update with no trace.
import { AlgoliaIndexAdapter } from "@evolve-framework/search-algolia";new AlgoliaIndexAdapter(options: AlgoliaIndexAdapterOptions<TRecord>)| Option | Type | Description |
|---|---|---|
appId | string | The Algolia application. |
writeApiKey | string | A key allowed to write and configure indices. Never give it a browser. |
resolveIndexName? | IndexNameResolver | Override index naming to match an existing convention. Defaults to
|
toRecord? | ((document: ProductDocument, scope: IndexScope) => TRecord | TRecord[]) | Override how a document becomes stored records. Returning several records
fans one document out; the sync engine's MoreThe scope is passed so a record can be written for the target it is going to — flattening localized values to the index's language, say. |
batchSize? | number | Algolia accepts up to 1000 objects per batch. |
atomicReindex? | boolean | Rebuild through a temporary index that is moved into place. Defaults to true, and there is rarely a reason to turn it off — a move to a destination that has replicas is supported and propagates the new data to them. MoreSetting it to |
| Method | Description |
|---|---|
init(): Promise<void> | One-shot, idempotent initialization (build SDK clients, etc.). |
upsertDocuments(
scope: IndexScope,
documents: ProductDocument[],
): Promise<void> | Write documents into the scope's target for each one's type, replacing any stored document with the same id as a whole. |
deleteDocuments(
scope: IndexScope,
ids: string[],
documentTypes: string[],
): Promise<void> | Remove ids from every declared type's index. |
deleteBySource(
scope: IndexScope,
sourceIds: string[],
options: DeleteBySourceOptions,
): Promise<void> | Remove every record a product owns, except the ids just written, across every declared type's index. |
applySettings(scope: IndexScope, settings: unknown): Promise<void> | Push provider index configuration (Algolia settings and replicas, …). |
AlgoliaQueryAdapter
Reads documents back out of Algolia.
Separate from the index adapter so an API deployment holds only a search key.
import { AlgoliaQueryAdapter } from "@evolve-framework/search-algolia";new AlgoliaQueryAdapter(options: AlgoliaQueryAdapterOptions<TRecord>)| Option | Type | Description |
|---|---|---|
appId | string | The Algolia application. |
searchApiKey | string | A search-only key: this adapter never writes. |
resolveIndexName? | IndexNameResolver | Defaults to |
toDocument? | ((record: TRecord, locale: string) => ProductDocument) | Inverse of the index adapter's MoreThe request's locale is passed so a record whose localized values were flattened for its index can be read back under the locale being asked for. |
buildQuery? | ((queries: SearchForHits[], query: ProductSearchQuery) => SearchForHits[]) | Adjust the queries before they are sent — rule contexts, optional
filters, |
distinct? | number | boolean | Deduplicate hits by the index's MoreRequired by the variant-record model: with a record per variant, a search
without this returns every variant of a product as its own row. Set it to
|
scopeGranularity? | "language" | "locale" | "store" | Must match the More
|
paginationLimitedTo? | number | The index's |
clickAnalytics? | boolean | Ask Algolia for a query id on every search, which click and conversion events send back so Insights attributes them to the search. Off by default, as Algolia only issues one when asked. |
querySuggestions? | boolean | Read suggestions from the index's Algolia Query Suggestions index, named
by |
| Method | Description |
|---|---|
init(): Promise<void> | Create the Algolia client from appId and searchApiKey. |
search(
query: ProductSearchQuery,
): Promise<SearchResponse<ProductDocument>> | Run a query and return the documents that matched. |
suggest(query: SuggestQuery): Promise<SuggestResponse> | Implement when capabilities.suggestions is true. |
Entry points
@evolve-framework/search-algolia | Both adapters, the index naming (defaultIndexName, localeIndexName), and the record mappers (toAlgoliaRecord and toProductDocument, toVariantRecord and fromVariantRecord)30 exports |
@evolve-framework/search-algolia/indexing | AlgoliaIndexAdapter2 exports |
@evolve-framework/search-algolia/query | AlgoliaQueryAdapter, plus buildQueries and mapFacets for a query adapter of your own5 exports |

