How to Create a Search Service
In this document, you’ll learn how to create a search service in the Medusa backend and the methods you must implement in it.
Prerequisites
A search service must extend the AbstractSearchService
class imported from the @medusajs/utils
package. If you don’t already have the package
installed, run the following command to install it within your project:
Overview
A search service class is in a TypeScript or JavaScript file created in the src/services
directory. The class must extend the AbstractSearchService
class imported
from the @medusajs/utils
package.
Based on services’ naming conventions, the file’s name should be the slug version of the search service’s name without service
, and the class’s name should be the
pascal case of the search service’s name following by Service
.
For example, create the MySearchService
class in the file src/services/my-search.ts
:
import { AbstractSearchService } from "@medusajs/utils"
class MySearchService extends AbstractSearchService {
isDefault = false
createIndex(indexName: string, options: Record<string, any>) {
throw new Error("Method not implemented.")
}
getIndex(indexName: string) {
throw new Error("Method not implemented.")
}
addDocuments(
indexName: string,
documents: Record<string, any>[],
type: string
) {
throw new Error("Method not implemented.")
}
replaceDocuments(
indexName: string,
documents: Record<string, any>[],
type: string
) {
throw new Error("Method not implemented.")
}
deleteDocument(
indexName: string,
document_id: string | number
) {
throw new Error("Method not implemented.")
}
deleteAllDocuments(indexName: string) {
throw new Error("Method not implemented.")
}
search(
indexName: string,
query: string,
options: Record<string, any>
) {
return {
message: "test",
}
}
updateSettings(
indexName: string,
settings: Record<string, any>
) {
throw new Error("Method not implemented.")
}
}
export default MySearchService
Notes About Class Methods
Although there are several helper methods in this class, the main methods used by the Medusa backend are addDocuments
, deleteDocument
, and search
.
The rest of the methods are provided in case you need them for custom use cases.
constructor
You can use the constructor
of your search service to access the different services in Medusa through dependency injection.
You can also use the constructor to initialize your integration with the third-party provider. For example, if you use a client to connect to the third-party provider’s APIs, you can initialize it in the constructor and use it in other methods in the service.
Additionally, if you’re creating your search service as an external plugin to be installed on any Medusa backend and you want to access the options added for the plugin,
you can access them in the constructor. The default constructor already sets the value of the class proeprty options_
to the passed options.
Example
// ...
import { ProductService } from "@medusajs/medusa"
type InjectedDependencies = {
productService: ProductService
}
class MySearchService extends AbstractSearchService {
// ...
protected readonly productService_: ProductService
constructor({ productService }: InjectedDependencies) {
// @ts-expect-error prefer-rest-params
super(...arguments)
this.productService_ = productService
// you can also initialize a client that
// communicates with a third-party service.
this.client = new Client(options)
}
// ...
}
Parameters
container
anyRequiredMedusaContainer
that allows you to access other resources, such as services, in your Medusa backend.options
anyRequiredProperties
isDefault
anyRequiredisDefault
property must be false
.options_
Record<string, unknown>RequiredMethods
createIndex
This method is used to create an index in the search engine.
Example
An example implementation, assuming client
would interact with a third-party service:
Another example of how the MeiliSearch plugin uses the
options
parameter:
Parameters
indexName
stringRequiredoptions
unknownRequiredReturns
unknown
unknownRequiredgetIndex
This method is used to retrieve an index’s results from the search engine.
Example
Parameters
indexName
stringRequiredReturns
unknown
unknownRequiredaddDocuments
This method is used to add a document to an index in the search engine.
When the Medusa backend loads, it triggers indexing for all products available in the Medusa backend, which uses this method to add or update documents. It’s also used whenever a new product is added or a product is updated.
Example
Parameters
indexName
stringRequireddocuments
unknownRequiredtype
stringRequiredproducts
.Returns
unknown
unknownRequiredreplaceDocuments
This method is used to replace existing documents in the search engine of an index with new documents.
Example
Parameters
indexName
stringRequireddocuments
unknownRequiredtype
stringRequiredproducts
.Returns
unknown
unknownRequireddeleteDocument
This method is used to delete a document from an index.
When a product is deleted in the Medusa backend, this method is used to delete the product from the search engine’s index.
Example
Parameters
indexName
stringRequireddocument_id
string | numberRequiredReturns
unknown
unknownRequireddeleteAllDocuments
This method is used to delete all documents from an index.
Example
Parameters
indexName
stringRequiredReturns
unknown
unknownRequiredsearch
This method is used to search through an index by a query.
In the Medusa backend, this method is used within the Search Products API Route to retrieve the search results. The API route's response type is an array of items, though the item's format is not defined as it depends on the data returned by this method.
Example
Parameters
indexName
stringRequiredproducts
.query
null | stringRequiredoptions
unknownRequiredpaginationOptions
: An object having anoffset
andlimit
properties, which are passed in the API Route's body.filter
: Filters that are passed in the API Route's request body. Its format is unknown, so you can pass filters based on your search service.additionalOptions
: Any other parameters that may be passed in the request's body.
Returns
unknown
unknownRequiredupdateSettings
This method is used to update the settings of an index within the search service. This is useful if you want to update the index settings when the plugin options change.
For example, in the Algolia plugin, a loader, which runs when the Medusa backend loads, is used to update the settings of indices based on the plugin options. The loader uses this method to update the settings.
Example
Parameters
indexName
stringRequiredsettings
unknownRequiredReturns
unknown
unknownRequiredTest Implementation
If you created your search service in a plugin, refer to this guide on how to test plugins.
After finishing your search service implementation:
1. Make sure you have an event bus module installed that triggers search indexing when the Medusa backend loads.
2. Run the build
command in the root of your Medusa backend:
3. Start the backend with the develop
command:
4. Try to search for products either using the Search Products API Route. The results returned by your search service's search
method is returned in the hits
response field.