Skip to main content

Local Search Filter

The Local Search filter provides full-text search using MongoDB's built-in text search capabilities.

Installation

import '@unchainedshop/plugins/filters/local-search';

Adapter Details

PropertyValue
Keyshop.unchained.filters.local-search
Order Index10
Version1.0.0
Sourcefilters/local-search.ts

Requirements

  • MongoDB text indexes on product and assortment text collections
  • Not compatible with AWS DocumentDB (automatically disabled in DocumentDB compat mode)

Behavior

searchProducts()

Searches product text fields using MongoDB $text operator:

// Search in product texts (title, description, etc.)
const selector = {
$text: { $search: queryString },
};

// If productIds provided, filter to those products
if (productIds) {
selector.productId = { $in: productIds };
}

searchAssortments()

Searches assortment/category text fields:

const selector = {
$text: { $search: queryString },
};

if (assortmentIds) {
selector.assortmentId = { $in: assortmentIds };
}

transformFilterSelector()

For global searches (no specific assortment), returns all active filters:

// When searching globally, show all filters
if (queryString && !filterIds) {
return { isActive: true };
}

Query Examples

query SearchProducts {
searchProducts(queryString: "running shoes") {
products {
_id
texts { title description }
}
filteredProductsCount
}
}

Combined Search and Filter

query SearchWithFilters {
searchProducts(
queryString: "organic cotton"
filterQuery: [
{ key: "category", value: "clothing" }
{ key: "size", value: "M" }
]
) {
products {
_id
texts { title }
}
filters {
filteredProductsCount
isSelected
options {
filteredProductsCount
isSelected
}
}
}
}

Search Assortments

query SearchCategories {
searchAssortments(queryString: "summer collection") {
assortments {
_id
texts { title }
}
}
}

Text Index Configuration

MongoDB text indexes are created automatically. The default indexes search:

Product Texts:

  • title
  • subtitle
  • description
  • vendor
  • brand
  • labels

Assortment Texts:

  • title
  • subtitle
  • description

Search Features

# Exact phrase
searchProducts(queryString: "\"running shoes\"")

Negation

# Exclude terms
searchProducts(queryString: "shoes -sandals")

Stemming

MongoDB applies stemming based on language:

  • "running" matches "run", "runs", "runner"

DocumentDB Compatibility

Local Search is automatically disabled when UNCHAINED_DOCUMENTDB_COMPAT_MODE is set:

UNCHAINED_DOCUMENTDB_COMPAT_MODE=true

In this case, implement an alternative search adapter using a service like:

  • Elasticsearch
  • Algolia
  • Meilisearch
  • OpenSearch

Custom Search Adapter

For external search services:

import { FilterDirector, FilterAdapter, type IFilterAdapter } from '@unchainedshop/core';

const AlgoliaSearchAdapter: IFilterAdapter = {
...FilterAdapter,

key: 'my-shop.algolia-search',
label: 'Algolia Search',
version: '1.0.0',
orderIndex: 10,

actions: (params) => {
const { searchQuery, modules } = params;

return {
...FilterAdapter.actions(params),

async searchProducts({ productIds }) {
const { queryString } = searchQuery;
if (!queryString) return productIds;

const algoliaClient = algoliasearch(
process.env.ALGOLIA_APP_ID,
process.env.ALGOLIA_API_KEY
);
const index = algoliaClient.initIndex('products');

const { hits } = await index.search(queryString, {
filters: productIds
? `productId:${productIds.join(' OR productId:')}`
: undefined,
hitsPerPage: 1000,
});

return hits.map(hit => hit.productId);
},

async searchAssortments({ assortmentIds }) {
const { queryString } = searchQuery;
if (!queryString) return assortmentIds;

const algoliaClient = algoliasearch(
process.env.ALGOLIA_APP_ID,
process.env.ALGOLIA_API_KEY
);
const index = algoliaClient.initIndex('assortments');

const { hits } = await index.search(queryString);
return hits.map(hit => hit.assortmentId);
},
};
},
};

FilterDirector.registerAdapter(AlgoliaSearchAdapter);

Performance Considerations

  1. Index optimization: Ensure text indexes exist and are properly configured
  2. Query limits: Use pagination for large result sets
  3. Projection: Only request needed fields
  4. Caching: Consider caching frequent searches