Search API

The Search API that uses the SearchService class allows Content SDK apps to query SitecoreAI search indexes to create tailored search experiences for different content types and user needs. This enables quick retrieval of content items and operations such as sorting, paginating, limiting results, etc. It abstracts the underlying search implementation and provides a consistent API.

The API has the following capabilities:

  • Use generic types to model documents for better IDE support and type safety

  • Sort results and use dot notation for nested properties

  • Limit and paginate results

  • Use custom fetch options for advanced use cases

Configuration

To initialize the SearchService class, you can create an instance of it using a configuration object as shown.

RequestResponse
import { SearchService } from '@sitecore-content-sdk/search';

const searchService = new SearchService({
  contextId: 'SITECORE_EDGE_CONTEXT_ID',
});

The object expects the SITECORE_EDGE_CONTEXT_ID that you can retrieve from the Developer settings tab of your environment in the SitecoreAI Deploy App. After initialization, you can use the search method of the SearchService to retrieve results from SitecoreAI.

Supported parameters

The search method expects the ID of the search index and also supports several other parameters used to sort, paginate, limit, and offset results.

Parameter

Type

Description

searchIndexID

string

The ID of the SitecoreAI search index to retrieve results from.

Required

keyphrase

string

Use phrases to search the index for specific content.

sort

Object or Array of objects

Specify an object or array of objects containing the name and order to sort results by.

limit

number

Specify the limit to restrict the number of results returned.

offset

number

Specify a number to drop that many results. Use with limit for pagination.

Examples

The following sections demonstrate examples using the SearchService for common scenarios.

A basic search only requires the searchIndexId. The default limit is 10, so it returns only 10 results.

RequestResponse
const response = await searchService.search({
  searchIndexId: '1234567890',
});

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

Search with keyphrase

You can also search using a keyphrase as shown:

RequestResponse
const response = await searchService.search({
  searchIndexId: '1234567890',
  keyphrase: 'sitecore',
});

console.log(`Found ${response.total} results matching "sitecore"`);

Search with a generic type

The SearchService supports TypeScript generics, allowing you to define the shape of your search document for type safety and better IDE support.

The following example demonstrates using a type called Article to retrieve results and display its contents. This ensures predictable results.

RequestResponse
import { SearchService } from '@sitecore-content-sdk/search';

type Article = {
  id: string;
  title: string;
  description: string;
  publishDate: string;
  author: {
    name: string;
    email: string;
  };
  tags: string[];
}

const searchService = new SearchService({
  contextId: 'your-context-id',
});

// TypeScript now knows the shape of the search document
const response = await searchService.search<Article>({
  searchIndexId: '1234567890',
  keyphrase: 'typescript',
});

// Type-safe access to properties
response.results.forEach((article) => {
  console.log(article.title);
  console.log(article.author.name); 
  console.log(article.tags.join(', '));
});

Search with basic sorting

The SearchService supports sorting results using a single object specifying the name and order. The following example sorts the search results by the publishDate in the descending order (most recent first).

RequestResponse
const response = await searchService.search({
  searchIndexId: '1234567890',
  keyphrase: 'article',
  sort: {
    name: 'publishDate',
    order: 'desc', // Most recent first
  },
});

Search with multi-field sorting

You can also specify multiple fields to sort. Instead of a single object, you should specify this as an array of objects. The following example sorts the search results by category in the ascending order, followed by price in ascending order, and finally by rating in the descending order.

RequestResponse
const response = await searchService.search({
  searchIndexId: '1234567890',
  keyphrase: 'electronics',
  sort: [
    {
      name: 'category',
      order: 'asc', // First sort by category
    },
    {
      name: 'price',
      order: 'asc', // Then by price within each category
    },
    {
      name: 'rating',
      order: 'desc', // Finally by rating (highest first)
    },
  ],
});

Search with type sorting

You can sort fields when you're using generics. TypeScript verifies the existence of the sort field in this case.

RequestResponse
type Product = {
  id: string;
  name: string;
  price: number;
  rating: number;
  category: string;
}

const response = await searchService.search<Product>({
  searchIndexId: '1234567890',
  sort: {
    name: 'category', // TypeScript hints that this field exists
    order: 'desc',
  },
});

/* TypeScript error: Property 'invalidField' does not exist
const invalidSort = {
  name: 'invalidField',
  order: 'asc',
};
*/

Search with nested sorting

Using dot notation (.), you can sort nested properties.

RequestResponse
type Order = {
  id: string;
  orderDate: string;
  customer: {
    name: string;
    email: string;
  };
  items: Array<{
    productId: string;
    quantity: number;
  }>;
}

const response = await searchService.search<Order>({
  searchIndexId: '1234567890',
  sort: {
    name: 'customer.name', // TypeScript hints that this field exists
    order: 'asc',
  },
});

Search with limited results

To limit the number of results returned, you can use the limit property. The default value is 10 and the maximum value allowed is 500.

RequestResponse
// Retrieve 5 results
const response = await searchService.search({
  searchIndexId: '1234567890',
  keyphrase: 'product',
  limit: 5,
});

// Retrieve up to 500 results
const response = await searchService.search({
  searchIndexId: '1234567890',
  keyphrase: 'article',
  limit: 500, // Maximum value
});

Search with pagination

Use the offset parameter to implement pagination. Combined with limit, you can fetch results in pages.

RequestResponse
async function getPage(
  searchService: SearchService,
  searchIndexId: string,
  keyphrase: string,
  page: number,
  pageSize: number = 10
) {
  const response = await searchService.search({
    searchIndexId,
    keyphrase,
    limit: pageSize,
    offset: (page - 1) * pageSize,
  });

  return {
    results: response.results,
    total: response.total,
    page,
    pageSize,
    totalPages: Math.ceil(response.total / pageSize),
  };
}

// Usage
const page1 = await getPage(searchService, 'your-search-index-id', 'article', 1, 10);
const page2 = await getPage(searchService, 'your-search-index-id', 'article', 2, 10);

Search with custom fetch options

The SearchService allows you to customize the underlying fetch request by passing a RequestInit object as the second parameter. This is useful for adding custom headers, setting timeouts, or configuring other request options.

Custom headers

You can set custom headers using the headers object containing key-value pairs of the header name and value.

RequestResponse
const response = await searchService.search(
  {
    searchIndexId: '1234567890',
    keyphrase: 'product',
  },
  {
    headers: {
      'X-Custom-Header': 'custom-value',
    },
  }
);

Request timeout

You can set a custom request timeout using the signal object that references the AbortController's signal property.

RequestResponse
// Using AbortController for timeout
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout

try {
  const response = await searchService.search(
    {
      searchIndexId: '1234567890',
      keyphrase: 'product',
    },
    {
      signal: controller.signal,
    }
  );

  clearTimeout(timeoutId);

  console.log(response.results);
} catch (error) {
  if (error.name === 'AbortError') {
    console.error('Request timed out');
  } else {
    throw error;
  }
}

Error handling

The SearchService throws specific errors that you should handle appropriately:

RequestResponse
try {
  const response = await searchService.search({
    searchIndexId: '1234567890',
    keyphrase: 'product',
    limit: 10,
  });
} catch (error) {
  if (error instanceof RangeError) {
    // Handle validation errors (limit, offset)
    console.error('Invalid parameter:', error.message);
  } else if (error instanceof TypeError) {
    // Handle type errors (missing searchIndexId, invalid sort)
    console.error('Type error:', error.message);
  } else if (error instanceof Error) {
    // Handle network/API errors
    console.error('Search failed:', error.message);
  }
}

Do you have some feedback for us?

If you have suggestions for improving this article,