Skip to main content

Search API

Base path: /api/search
File: ayts-api/src/routes/search.ts
Auth required: No

GET /api/search

Full-text search across stores and products.

Query params:

ParamTypeDescription
qstringSearch query (required)
typeall|stores|productsScope (default: all)
categorystringFilter by category
limitnumberMax results (default: 20)
offsetnumberPagination offset

Response 200:

{
"success": true,
"query": "rice",
"results": {
"stores": [{
"id": "uuid",
"name": "Fresh Mart Grocery",
"category": "grocery",
"rating": 4.5
}],
"products": [{
"id": "uuid",
"name": "Sinandomeng Rice 5kg",
"price": 285.00,
"store": { "id": "uuid", "name": "Fresh Mart Grocery" }
}]
},
"total": { "stores": 3, "products": 12 }
}

GET /api/search/autocomplete

Returns autocomplete suggestions as the user types.

Query params: q (min 2 chars), limit (default: 5)

Response 200:

{
"success": true,
"suggestions": [
{ "type": "product", "text": "Sinandomeng Rice 5kg", "id": "uuid" },
{ "type": "store", "text": "Fresh Mart Grocery", "id": "uuid" }
]
}

Implementation

Uses PostgreSQL FTS with to_tsvector + to_tsquery:

-- Products FTS index
CREATE INDEX idx_products_fts
ON products USING GIN(to_tsvector('english', name || ' ' || coalesce(description, '')));

-- Stores FTS index
CREATE INDEX idx_stores_fts
ON stores USING GIN(to_tsvector('english', name || ' ' || coalesce(description, '')));

Query:

SELECT * FROM products
WHERE to_tsvector('english', name || ' ' || coalesce(description, ''))
@@ plainto_tsquery('english', $1)
ORDER BY ts_rank(...) DESC;