Skip to main content

Usage

This page provides practical examples and API reference for using the Algolia integration.

API endpoint

The integration provides access to search functionality through the framework's search controller:

Performs a search query against a specified Algolia index.

Endpoint: GET /search?index={indexName}

Query parameters:

parametertypedescriptionrequired
indexstringName of the Algolia indexyes

Request body:

The request body should contain a SearchPayload object with search parameters.

Response:

Returns a SearchResult<T> object with search results.

Example using cURL:

curl -X GET "http://localhost:3000/search?index=articles" \
-H "Content-Type: application/json" \
-d '{
"query": "getting started",
"locale": "en",
"pagination": {
"limit": 10,
"offset": 0
}
}'

SearchPayload structure

The SearchPayload class defines the structure for search queries. All fields are optional and can be combined.

fieldtypedescription
querystringText search query
localestringFilter results by locale (e.g., "en", "pl")
exactRecord<string, string | number | boolean | null | object | array>Exact match filters (converted to Algolia facet filters)
rangeRecord<string, { min?: string | number | Date | boolean; max?: string | number | Date | boolean }>Range filters for numeric or date fields (converted to Algolia numeric filters)
pagination{ offset?: number; limit?: number }Pagination parameters
sortArray<{ field: string; order: 'asc' | 'desc' }>Sort configuration (only first element used, modifies index name)

Note: The exists, notExists, and filter fields from SearchPayload are not implemented in the Algolia integration.

Query examples

Simple text search:

{
"query": "getting started"
}

With locale filter:

{
"query": "documentation",
"locale": "en"
}

With exact filters:

{
"query": "tutorial",
"exact": {
"category": "guides",
"status": "published",
"tags": ["javascript", "typescript"]
}
}

With range filters:

{
"range": {
"price": {
"min": 500,
"max": 2000
},
"publishedAt": {
"min": "2024-01-01"
}
}
}

With pagination:

{
"pagination": {
"limit": 20,
"offset": 40
}
}

With sorting:

{
"sort": [
{
"field": "publishedAt",
"order": "desc"
}
]
}

Note: Sorting modifies the index name. You need an index named articles_publishedAt_desc for the above example to work.

SearchResult structure

The SearchResult<T> class defines the structure of search responses.

fieldtypedescription
hitsT[]Array of search results matching the query
totalnumberTotal number of matching results
pagenumberCurrent page number (if pagination is used)
nbPagesnumberTotal number of pages (if pagination is used)
processingTimeMSnumberQuery processing time in milliseconds

Usage examples

SDK imports

For article search, use the article-search block SDK:

import { sdk } from '@o2s/blocks.article-search/sdk';

For generic search, use the framework SDK:

import { sdk } from '@o2s/framework/sdk';

Example 1: Article search

Using SDK for article search (recommended):

import { sdk } from '@o2s/blocks.article-search/sdk';

const results = await sdk.blocks.searchArticles(
{
query: 'getting started',
limit: 10,
offset: 0,
category: 'guides', // Optional: filters by category
},
{ 'x-locale': 'en' }
);

console.log(`Found ${results.total} articles`);
results.articles.forEach(article => {
console.log(`- ${article.title}`);
});

Using SDK for generic search:

import { sdk } from '@o2s/framework/sdk';

const results = await sdk.makeRequest<SearchResult<Product>>({
method: 'get',
url: '/search',
params: { index: 'products' },
data: {
query: 'laptop',
locale: 'en',
exact: {
status: 'available',
},
range: {
price: {
min: 500,
max: 2000,
},
},
pagination: {
limit: 20,
offset: 0,
},
},
headers: {
'Content-Type': 'application/json',
'x-locale': 'en',
},
});

console.log(`Found ${results.total} results`);
results.hits.forEach(hit => {
console.log(hit);
});

Example 3: Frontend search component

Using SDK for article search:

'use client';

import { useState } from 'react';
import { sdk } from '@o2s/blocks.article-search/sdk';

const ArticleSearch = ({ locale }: { locale: string }) => {
const [query, setQuery] = useState('');
const [results, setResults] = useState<{ articles: Array<{ id: string; title: string }>; total: number } | null>(null);
const [loading, setLoading] = useState(false);

const handleSearch = async () => {
if (!query.trim()) return;

setLoading(true);
try {
const data = await sdk.blocks.searchArticles(
{
query,
limit: 10,
offset: 0,
},
{ 'x-locale': locale }
);
setResults(data);
} catch (error) {
console.error('Search failed:', error);
} finally {
setLoading(false);
}
};

return (
<div>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search articles..."
onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
/>
<button onClick={handleSearch} disabled={loading}>
{loading ? 'Searching...' : 'Search'}
</button>
{results && (
<div>
<p>Found {results.total} results</p>
{results.articles.map((article) => (
<div key={article.id}>{article.title}</div>
))}
</div>
)}
</div>
);
};

Error handling

Missing environment variables

Error: Please provide a valid Algolia app ID or Please provide a valid Algolia API key

When it occurs: During service initialization

Solution: Ensure both ALGOLIA_APP_ID and ALGOLIA_API_KEY are set in your environment variables.

Missing index name

Error: Index name is required

When it occurs: When calling search methods without providing an index name

Solution: Always provide an indexName parameter when calling search methods.

Index not found (404)

Error: Logged as: Algolia index with name {indexName} not found, please check your environment variables

Behavior: Returns an empty result set:

{
"hits": [],
"total": 0
}

Solution:

  • Verify the index name is correct
  • Ensure the index exists in your Algolia dashboard
  • Check that your API key has read access to the index

Other API errors

Behavior: Errors are logged with full details and re-thrown to be handled by the framework's error handling system.

Solution: Check the error logs for specific details about the API error.

Best practices

  1. Use search-only API keys: Never use admin keys with write permissions in your application
  2. Index naming for sorting: Create separate indexes for each sort configuration (e.g., articles_publishedAt_desc)
  3. Pagination: Use appropriate page sizes (10-50 items) for better performance
  4. Error handling: Always handle errors gracefully and provide fallback behavior
  5. Logging: Enable debug logging during development to see query details
  6. Index configuration: Configure your Algolia indexes properly with appropriate attributes for faceting and filtering
  7. Locale filtering: Use locale filtering to ensure users only see content in their language
  8. Combine filters: Use exact and range filters together for precise results

Pagination notes

The integration converts offset to Algolia's page parameter:

  • Formula: page = Math.floor(offset / limit)
  • Default limit: 20 (if not specified)
  • Example: offset: 40, limit: 20page: 2

To get page 3 with 10 items per page:

{
pagination: {
limit: 10,
offset: 20 // (page 3 - 1) * 10 = 20
}
}