Manufacturer Aliases Integration Guide
This document explains how to integrate the manufacturer alias normalization system into the search autocomplete pipeline. The alias system enables queries...
Manufacturer Aliases Integration Guide
Overview
This document explains how to integrate the manufacturer alias normalization system into the search autocomplete pipeline. The alias system enables queries like "newh" to return "New Holland" results, fixing the gap in partial manufacturer name matching.
Problem Statement
Query "newh" returns empty results because:
- Elasticsearch prefix/term matching looks for exact field values
- "newh" doesn't match "New Holland" in the index
- The autocomplete query (lines 1061-1130 in autocomplete-suggestions.ts) has no alias expansion
Solution Architecture
Components
-
Alias Mapping (
packages/shared-catalog/src/config/manufacturers.ts)DEFAULT_ALIASES: Record mapping aliases to manufacturer infonormalizeManufacturerQuery(query): Convert alias to canonical nameasManufacturer(key): Get manufacturer info from alias or key
-
Normalization Helpers (same module)
normalizeManufacturerQuery(query): Resolve aliases to canonical namesasManufacturer(key): Reverse lookup from alias/code/name to canonical object
-
Tests
services/search/src/__tests__/manufacturer-aliases.test.ts: Unit testsservices/search/src/__tests__/routes/autocomplete/manufacturer-aliases-integration.test.ts(Optional): Integration tests
Alias Mapping Reference
New Holland Aliases
nh → New Holland
newh → New Holland
new-holland → New Holland
newholland → New Holland
new holland → New HollandOther Manufacturers
mch, mchale → McHale
briggs, bgs, briggs-stratton → Briggs & Stratton
gp, great-plains → Great Plains
cc, clubcar, club-car → Club Car
kws, kawasaki → Kawasaki
ven, ventrac → Ventrac
ezt, ez-trail → EZ-Trail
hsy, hotsy → Hotsy
dio, dion, dion ag → Dion AG
amc, amco → AMCO
ht, harvesttec, harvest-tec → Harvest Tec
agb, ag-bag → Ag-Bag
hla → HLAIntegration into Autocomplete
Current Manufacturer Query (Lines 1061-1130)
// 4) Manufacturers aggregation with multi-field search
if (!skipExpensiveQueries && caps.manufacturer > 0) {
const lowerQuery = query.toLowerCase();
searches.push({ index: indexName, preference });
searches.push({
size: 0,
_source: false,
query: {
bool: {
should: [
{
term: {
'manufacturer.code': {
value: lowerQuery,
boost: 10,
},
},
},
// ... other matches
],
},
},
aggs: {
manufacturers: {
terms: {
field: 'manufacturer.name.keyword',
size: caps.manufacturer,
},
},
},
});
}Enhanced Implementation
Add alias expansion to the manufacturer query:
import { normalizeManufacturerQuery } from '@crop/shared-catalog';
// 4) Manufacturers aggregation with multi-field search + alias expansion
if (!skipExpensiveQueries && caps.manufacturer > 0) {
const lowerQuery = query.toLowerCase();
// NEW: Check for manufacturer aliases
const normalizedMfgNames = normalizeManufacturerQuery(lowerQuery);
searches.push({ index: indexName, preference });
searches.push({
size: 0,
_source: false,
track_total_hits: false,
timeout: '100ms',
query: {
bool: {
should: [
// 1. Exact manufacturer code match (highest priority)
{
term: {
'manufacturer.code': {
value: lowerQuery,
boost: 10,
},
},
},
// 2. Exact name match
{
term: {
'manufacturer.name.keyword': {
value: query,
boost: 5,
case_insensitive: true,
},
},
},
// NEW: 2b. Alias expansion match (normalized manufacturer names)
...(normalizedMfgNames.length > 0
? [
{
terms: {
'manufacturer.name.keyword': normalizedMfgNames,
boost: 4.5,
},
},
]
: []),
// 3. Suggest analyzer match
{
match: {
'manufacturer.name.suggest': {
query: lowerQuery,
minimum_should_match: '75%',
boost: 3,
},
},
},
// 4. Ngram match
{
match: {
'manufacturer.name.ngram': {
query: lowerQuery,
minimum_should_match: '50%',
boost: 1,
},
},
},
],
minimum_should_match: 1,
filter: lockFilters.length > 0 ? lockFilters : undefined,
},
},
aggs: {
manufacturers: {
terms: {
field: 'manufacturer.name.keyword',
size: caps.manufacturer,
shard_size: caps.manufacturer * 3,
min_doc_count: 1,
order: { _count: 'desc' },
},
},
},
});
}Usage Examples
Example 1: Query "newh"
Before Integration:
Query: "newh"
Results: [] (empty)After Integration:
Query: "newh"
Normalized: ["New Holland"]
Elasticsearch Query: terms { manufacturer.name: ["New Holland"] }
Results: [New Holland manufacturers]Example 2: Query "nh"
Query: "nh"
Normalized: ["New Holland"]
Results: [New Holland manufacturers]Example 3: Query "briggs"
Query: "briggs"
Normalized: ["Briggs & Stratton"]
Results: [Briggs & Stratton manufacturers]Example 4: Query "hydraulic" (no manufacturer)
Query: "hydraulic"
Normalized: [] (no match)
Results: [proceed with normal matching]Performance Considerations
Memory
DEFAULT_ALIASESmap: ~2KB (50+ aliases)- Single query normalization: O(1) lookup time
- No additional memory allocation needed
CPU
- Alias lookup: < 0.05ms per query (1000 queries in < 50ms)
- Negligible overhead compared to Elasticsearch round-trip
Network
- No additional ES requests (alias expansion happens client-side)
- Potentially fewer ES queries if alias match prevents fallback queries
Testing
Unit Tests
bun test src/__tests__/manufacturer-aliases.test.tsCoverage:
- ✅ New Holland aliases: newh, nh, new-holland, newholland, new holland
- ✅ Other manufacturer aliases
- ✅ Case insensitivity
- ✅ Edge cases (empty, whitespace, unknown)
- ✅ Performance (1000 queries < 50ms)
Manual Testing
Test Query 1: Partial alias
curl "http://localhost:3001/api/autocomplete?q=newh"Expected: New Holland should appear in suggestions
Test Query 2: Code alias
curl "http://localhost:3001/api/autocomplete?q=nh"Expected: New Holland should appear in suggestions
Test Query 3: Spaced alias
curl "http://localhost:3001/api/autocomplete?q=new%20holland"Expected: New Holland should appear in suggestions
Test Query 4: Non-manufacturer word
curl "http://localhost:3001/api/autocomplete?q=hydraulic"Expected: Normal search behavior (no alias expansion, but hydraulic results)
Implementation Checklist
- Review manufacturer aliases in
DEFAULT_ALIASESmap - Add aliases for any missing manufacturers
- Update autocomplete-suggestions.ts with alias expansion logic
- Add import:
import { normalizeManufacturerQuery } from '@crop/shared-catalog'; - Update manufacturer query section (lines 1061-1130)
- Run unit tests:
bun test src/__tests__/manufacturer-aliases.test.ts - Run full test suite:
bun test - Manual testing with real autocomplete queries
- Deploy and monitor autocomplete suggestions
Configuration
Disabling Alias Expansion (if needed)
To temporarily disable alias expansion:
import { normalizeManufacturerQuery } from '@crop/shared-catalog';
const normalized = normalizeManufacturerQuery(query);
// Temporarily skip using `normalized` if you want to disable alias expansionAdjusting Boost Values
The terms query boost (4.5 in the example) controls how much the alias match contributes to relevance:
{
terms: {
'manufacturer.name.keyword': normalizedMfgNames,
boost: 4.5, // Adjust this value
},
}- Higher boost = more weight for alias matches
- 4.5 balances alias matches with code/name matches
- Adjust based on autocomplete quality metrics
Monitoring & Debugging
Enable Query Logging
export ES_LOG_QUERIES=true
bun run devLook for manufacturer aggregation queries to verify alias expansion is working.
Check Alias Resolution
import { DEFAULT_ALIASES, normalizeManufacturerQuery } from '@crop/shared-catalog';
// Check what aliases exist for a manufacturer
const aliases = Object.entries(DEFAULT_ALIASES)
.filter(([_, info]) => info.name === "New Holland")
.map(([alias]) => alias);
console.log(aliases); // ["nh", "newh", "new-holland", ...]
// Check how a query normalizes
const canonical = normalizeManufacturerQuery("newh");
console.log(canonical[0]); // "New Holland"Future Enhancements
1. User-Defined Aliases
Allow API admins to add custom manufacturer aliases:
POST /api/admin/manufacturer-aliases
{ "alias": "holland", "manufacturerName": "New Holland" }2. Prefix Matching for Short Queries
Expand prefix matching for very short queries (< 3 chars):
// "ne" → should it match "New Holland"?
// Current: No (security/performance reason)
// Future: Configurable threshold3. Fuzzy Matching Enhancement
Combine alias system with fuzzy matching:
// "neww" (typo) → should it match "newh"?
// Current: Uses existing fuzzy in Elasticsearch
// Future: Could apply here too4. Metrics & Analytics
Track which aliases are used:
aliasUsageMetrics.inc({
alias: "newh",
manufacturerName: "New Holland",
});Related Files
packages/shared-catalog/src/config/manufacturers.ts- Alias definitionsservices/search/src/utils/autocomplete-suggestions.ts- Integration point (lines 1061-1130)services/search/src/__tests__/manufacturer-aliases.test.ts- Unit testsservices/search/src/__tests__/manufacturer-detector.test.ts- Existing manufacturer detection tests
See Also
Manufacturer Aliases System - Delivery Summary
Successfully created a complete manufacturer alias mapping system that enables partial manufacturer name queries (like "newh") to return "New Holland" results...
Manufacturer Aliases Reference
The manufacturer alias system enables partial manufacturer name queries to work in autocomplete. For example: - "newh" → "New Holland" - "nh" → "New Holland" -...