Meilisearch | Meilisearch Cloud | Documentation | Discord | Roadmap | Website | FAQ
⚡ The Meilisearch API client written for JavaScript
Meilisearch JavaScript is the Meilisearch API client for JavaScript developers.
Meilisearch is an open-source search engine. Learn more about Meilisearch.
- 📖 Documentation
- 🔧 Installation
- 🚀 Getting started
- 🤖 Compatibility with Meilisearch
- 💡 Learn more
- ⚙️ Contributing
- 📜 API resources
This readme and Meilisearch JS documentation website contains all the information you need to start using this Meilisearch SDK.
For general information on how to use Meilisearch—such as our API reference, tutorials, guides, and in-depth articles—refer to our main documentation website.
This package is published to npm.
Installing with npm
:
npm i meilisearch
Note
Node.js LTS and Maintenance versions are supported and tested. Other versions may or may not work.
Other runtimes, like Deno and Bun, aren't tested, but if they do not work with this package, please open an issue.
⚡️ Launch, scale, and streamline in minutes with Meilisearch Cloud—no maintenance, no commitment, cancel anytime. Try it free now.
🪨 Prefer to self-host? Download and deploy our fast, open-source search engine on your own infrastructure.
After installing meilisearch-js
, you must import it into your application. There are many ways of doing that depending on your development environment.
- TypeScript >= 4.7 is required
tsconfig.json
has to be set up correctly- take a look at Centralized Recommendations for TSConfig bases
Warning
- default export is deprecated and will be removed in a future version | Issue
- regarding usage of package's UMD version via
script src
, exports will stop being directly available on the global object | Issue
Usage in an ES module environment:
import { MeiliSearch } from "meilisearch";
const client = new MeiliSearch({
host: "http://127.0.0.1:7700",
apiKey: "masterKey",
});
This package also contains a UMD bundled
version, which in this case is meant to be used in a
script src
tag:
<script src="https://www.unpkg.com/meilisearch/dist/umd/index.min.js"></script>
<script>
const client = new meilisearch.MeiliSearch(/* ... */);
// ...
</script>
But keep in mind that each CDN (JSDELIVR, ESM.SH, etc.) provide more ways to import packages, make sure to read their documentation.
Usage in a back-end node.js or another environment supporting CommonJS modules:
const { MeiliSearch } = require("meilisearch");
const client = new MeiliSearch({
host: "http://127.0.0.1:7700",
apiKey: "masterKey",
});
To use meilisearch-js
with React Native, you must also install react-native-url-polyfill.
Usage in a Deno environment:
import { MeiliSearch } from "npm:meilisearch";
const client = new MeiliSearch({
host: "http://127.0.0.1:7700",
apiKey: "masterKey",
});
Take a look at the playground for a concrete example.
const { MeiliSearch } = require('meilisearch')
// Or if you are in a ES environment
import { MeiliSearch } from 'meilisearch'
;(async () => {
const client = new MeiliSearch({
host: 'http://127.0.0.1:7700',
apiKey: 'masterKey',
})
// An index is where the documents are stored.
const index = client.index('movies')
const documents = [
{ id: 1, title: 'Carol', genres: ['Romance', 'Drama'] },
{ id: 2, title: 'Wonder Woman', genres: ['Action', 'Adventure'] },
{ id: 3, title: 'Life of Pi', genres: ['Adventure', 'Drama'] },
{ id: 4, title: 'Mad Max: Fury Road', genres: ['Adventure', 'Science Fiction'] },
{ id: 5, title: 'Moana', genres: ['Fantasy', 'Action']},
{ id: 6, title: 'Philadelphia', genres: ['Drama'] },
]
// If the index 'movies' does not exist, Meilisearch creates it when you first add the documents.
let response = await index.addDocuments(documents)
console.log(response) // => { "uid": 0 }
})()
Tasks such as document addition always return a unique identifier. You can use this identifier taskUid
to check the status (enqueued
, canceled
, processing
, succeeded
or failed
) of a task.
// Meilisearch is typo-tolerant:
const search = await index.search('philoudelphia')
console.log(search)
Output:
{
"hits": [
{
"id": "6",
"title": "Philadelphia",
"genres": ["Drama"]
}
],
"offset": 0,
"limit": 20,
"estimatedTotalHits": 1,
"processingTimeMs": 1,
"query": "philoudelphia"
}
meilisearch-js
supports all search parameters described in our main documentation website.
await index.search(
'wonder',
{
attributesToHighlight: ['*']
}
)
{
"hits": [
{
"id": 2,
"title": "Wonder Woman",
"genres": ["Action", "Adventure"],
"_formatted": {
"id": "2",
"title": "<em>Wonder</em> Woman",
"genres": ["Action", "Adventure"]
}
}
],
"offset": 0,
"limit": 20,
"estimatedTotalHits": 1,
"processingTimeMs": 0,
"query": "wonder"
}
To enable filtering, you must first add your attributes to the filterableAttributes
index setting.
await index.updateFilterableAttributes([
'id',
'genres'
])
You only need to perform this operation once per index.
Note that Meilisearch rebuilds your index whenever you update filterableAttributes
. Depending on the size of your dataset, this might take considerable time. You can track the process using the tasks API).
After you configured filterableAttributes
, you can use the filter
search parameter to refine your search:
await index.search(
'wonder',
{
filter: ['id > 1 AND genres = Action']
}
)
{
"hits": [
{
"id": 2,
"title": "Wonder Woman",
"genres": ["Action","Adventure"]
}
],
"offset": 0,
"limit": 20,
"estimatedTotalHits": 1,
"processingTimeMs": 0,
"query": "wonder"
}
Placeholder search makes it possible to receive hits based on your parameters without having any query (q
). For example, in a movies database you can run an empty query to receive all results filtered by genre
.
await index.search(
'',
{
filter: ['genres = fantasy'],
facets: ['genres']
}
)
{
"hits": [
{
"id": 2,
"title": "Wonder Woman",
"genres": ["Action","Adventure"]
},
{
"id": 5,
"title": "Moana",
"genres": ["Fantasy","Action"]
}
],
"offset": 0,
"limit": 20,
"estimatedTotalHits": 2,
"processingTimeMs": 0,
"query": "",
"facetDistribution": {
"genres": {
"Action": 2,
"Fantasy": 1,
"Adventure": 1
}
}
}
Note that to enable faceted search on your dataset you need to add genres
to the filterableAttributes
index setting. For more information on filtering and faceting, consult our documentation settings.
You can abort a pending search request by providing an AbortSignal to the request.
const controller = new AbortController()
index
.search('wonder', {}, {
signal: controller.signal,
})
.then((response) => {
/** ... */
})
.catch((e) => {
/** Catch AbortError here. */
})
controller.abort()
You can provide a custom request configuration. for example, with custom headers.
const client: MeiliSearch = new MeiliSearch({
host: 'http://localhost:3000/api/meilisearch/proxy',
requestConfig: {
headers: {
Authorization: AUTH_TOKEN
},
// OR
credentials: 'include'
}
})
You can use your own HTTP client, for example, with axios
.
const client: MeiliSearch = new MeiliSearch({
host: 'http://localhost:3000/api/meilisearch/proxy',
httpClient: async (url, opts) => {
const response = await $axios.request({
url,
data: opts?.body,
headers: opts?.headers,
method: (opts?.method?.toLocaleUpperCase() as Method) ?? 'GET'
})
return response.data
}
})
This package guarantees compatibility with version v1.x of Meilisearch, but some features may not be present. Please check the issues for more info.
The following sections in our main documentation website may interest you:
- Manipulate documents: see the API references or read more about documents.
- Search: see the API references or follow our guide on search parameters.
- Manage the indexes: see the API references or read more about indexes.
- Configure the index settings: see the API references or follow our guide on settings parameters.
This repository also contains more examples.
We welcome all contributions, big and small! If you want to know more about this SDK's development workflow or want to contribute to the repo, please visit our contributing guidelines for detailed instructions.
client.index<T>('xxx').search(query: string, options: SearchParams = {}, config?: Partial<Request>): Promise<SearchResponse<T>>
client.index<T>('xxx').searchGet(query: string, options: SearchParams = {}, config?: Partial<Request>): Promise<SearchResponse<T>>
client.multiSearch(queries?: MultiSearchParams, config?: Partial<Request>): Promise<Promise<MultiSearchResponse<T>>>
multiSearch
uses the POST
method when performing its request to Meilisearch.
client.index<T>('myIndex').searchForFacetValues(params: SearchForFacetValuesParams, config?: Partial<Request>): Promise<SearchForFacetValuesResponse>
client.index('myIndex').addDocuments(documents: Document<T>[]): Promise<EnqueuedTask>
client.index('myIndex').addDocumentsFromString(documents: string, contentType: ContentType, queryParams: RawDocumentAdditionOptions): Promise<EnqueuedTask>
client.index('myIndex').addDocumentsInBatches(documents: Document<T>[], batchSize = 1000): Promise<EnqueuedTask[]>
client.index('myIndex').updateDocuments(documents: Array<Document<Partial<T>>>): Promise<EnqueuedTask>
client.index('myIndex').updateDocumentsFromString(documents: string, contentType: ContentType, queryParams: RawDocumentAdditionOptions): Promise<EnqueuedTask>
client.index('myIndex').updateDocumentsInBatches(documents: Array<Document<Partial<T>>>, batchSize = 1000): Promise<EnqueuedTask[]>
client.index.getDocuments(parameters: DocumentsQuery = {}): Promise<DocumentsResults<T>>>
client.index('myIndex').getDocument(documentId: string): Promise<Document<T>>
client.index('myIndex').deleteDocument(documentId: string | number): Promise<EnqueuedTask>
client.index('myIndex').deleteDocuments(params: DocumentsDeletionQuery | DocumentsIds): Promise<EnqueuedTask>
client.index('myIndex').deleteAllDocuments(): Promise<Types.EnqueuedTask>
client.getTasks(parameters: TasksQuery): Promise<TasksResults>
client.getTask(uid: number): Promise<Task>
client.deleteTasks(parameters: DeleteTasksQuery = {}): Promise<EnqueuedTask>
client.cancelTasks(parameters: CancelTasksQuery = {}): Promise<EnqueuedTask>
client.index('myIndex').getTasks(parameters: TasksQuery): Promise<TasksResults>
client.index('myIndex').getTask(uid: number): Promise<Task>
client.waitForTask(uid: number, { timeOutMs?: number, intervalMs?: number }): Promise<Task>
client.index('myIndex').waitForTask(uid: number, { timeOutMs?: number, intervalMs?: number }): Promise<Task>
client.waitForTasks(uids: number[], { timeOutMs?: number, intervalMs?: number }): Promise<Task[]>
client.index('myIndex').waitForTasks(uids: number[], { timeOutMs?: number, intervalMs?: number }): Promise<Task[]>
client.getBatch(uid: number): Promise<Batch>
client.getBatches(parameters: BatchesQuery = {}): Promise<BatchesResults>
client.getIndexes(parameters: IndexesQuery): Promise<IndexesResults<Index[]>>
client.getRawIndexes(parameters: IndexesQuery): Promise<IndexesResults<IndexObject[]>>
client.createIndex<T>(uid: string, options?: IndexOptions): Promise<EnqueuedTask>
client.index<T>(uid: string): Index<T>
client.getIndex<T>(uid: string): Promise<Index<T>>
client.getRawIndex(uid: string): Promise<IndexObject>
client.index('myIndex').getRawInfo(): Promise<IndexObject>
client.updateIndex(uid: string, options: IndexOptions): Promise<EnqueuedTask>
client.index('myIndex').update(data: IndexOptions): Promise<EnqueuedTask>
client.deleteIndex(uid): Promise<void>
client.index('myIndex').delete(): Promise<void>
client.index('myIndex').getStats(): Promise<IndexStats>
client.index('myIndex').fetchInfo(): Promise<Index>
client.index('myIndex').fetchPrimaryKey(): Promise<string | undefined>
client.swapIndexes(params: SwapIndexesParams): Promise<EnqueuedTask>
client.index('myIndex').getSettings(): Promise<Settings>
client.index('myIndex').updateSettings(settings: Settings): Promise<EnqueuedTask>
client.index('myIndex').resetSettings(): Promise<EnqueuedTask>
client.index('myIndex').getPagination(): Promise<PaginationSettings>
client.index('myIndex').updatePagination(pagination: PaginationSettings): Promise<EnqueuedTask>
client.index('myIndex').resetPagination(): Promise<EnqueuedTask>
client.index('myIndex').getSynonyms(): Promise<Synonyms>
client.index('myIndex').updateSynonyms(synonyms: Synonyms): Promise<EnqueuedTask>
client.index('myIndex').resetSynonyms(): Promise<EnqueuedTask>
client.index('myIndex').getStopWords(): Promise<string[]>
client.index('myIndex').updateStopWords(stopWords: string[] | null ): Promise<EnqueuedTask>
client.index('myIndex').resetStopWords(): Promise<EnqueuedTask>
client.index('myIndex').getRankingRules(): Promise<string[]>
client.index('myIndex').updateRankingRules(rankingRules: string[] | null): Promise<EnqueuedTask>
client.index('myIndex').resetRankingRules(): Promise<EnqueuedTask>
client.index('myIndex').getDistinctAttribute(): Promise<string | void>
client.index('myIndex').updateDistinctAttribute(distinctAttribute: string | null): Promise<EnqueuedTask>
client.index('myIndex').resetDistinctAttribute(): Promise<EnqueuedTask>
client.index('myIndex').getSearchableAttributes(): Promise<string[]>
client.index('myIndex').updateSearchableAttributes(searchableAttributes: string[] | null): Promise<EnqueuedTask>
client.index('myIndex').resetSearchableAttributes(): Promise<EnqueuedTask>
client.index('myIndex').getDisplayedAttributes(): Promise<string[]>
client.index('myIndex').updateDisplayedAttributes(displayedAttributes: string[] | null): Promise<EnqueuedTask>
client.index('myIndex').resetDisplayedAttributes(): Promise<EnqueuedTask>
client.index('myIndex').getFilterableAttributes(): Promise<string[]>
client.index('myIndex').updateFilterableAttributes(filterableAttributes: string[] | null): Promise<EnqueuedTask>
client.index('myIndex').resetFilterableAttributes(): Promise<EnqueuedTask>
client.index('myIndex').getSortableAttributes(): Promise<string[]>
client.index('myIndex').updateSortableAttributes(sortableAttributes: string[] | null): Promise<EnqueuedTask>
client.index('myIndex').resetSortableAttributes(): Promise<EnqueuedTask>
client.index('myIndex').getFaceting(): Promise<Faceting>
client.index('myIndex').updateFaceting(faceting: Faceting): Promise<EnqueuedTask>
client.index('myIndex').resetFaceting(): Promise<EnqueuedTask>
client.index('myIndex').getTypoTolerance(): Promise<TypoTolerance>
client.index('myIndex').updateTypoTolerance(typoTolerance: TypoTolerance | null): Promise<EnqueuedTask>
client.index('myIndex').resetTypoTolerance(): Promise<EnqueuedTask>
client.index('myIndex').getSeparatorTokens(): Promise<SeparatorTokens>
client.index('myIndex').updateSeparatorTokens(separatorTokens: SeparatorTokens | null): Promise<EnqueuedTask>
client.index('myIndex').resetSeparatorTokens(): Promise<EnqueuedTask>
client.index('myIndex').getNonSeparatorTokens(): Promise<NonSeparatorTokens>
client.index('myIndex').updateNonSeparatorTokens(nonSeparatorTokens: NonSeparatorTokens | null): Promise<EnqueuedTask>
client.index('myIndex').resetNonSeparatorTokens(): Promise<EnqueuedTask>
client.index('myIndex').getDictionary(): Promise<Dictionary>
client.index('myIndex').updateDictionary(dictionary: Dictionary | null): Promise<EnqueuedTask>
client.index('myIndex').resetDictionary(): Promise<EnqueuedTask>
client.index('myIndex').getProximityPrecision(): Promise<ProximityPrecision>
client.index('myIndex').updateProximityPrecision(proximityPrecision: ProximityPrecision): Promise<EnqueuedTask>
client.index('myIndex').resetProximityPrecision(): Promise<EnqueuedTask>
client.index('myIndex').getFacetSearch(): Promise<boolean>
client.index('myIndex').updateFacetSearch(enabled: boolean): Promise<EnqueuedTask>
client.index('myIndex').resetFacetSearch(): Promise<EnqueuedTask>
client.index('myIndex').getPrefixSearch(): Promise<PrefixSearch>
client.index('myIndex').updatePrefixSearch(prefixSearch: PrefixSearch): Promise<EnqueuedTask>
client.index('myIndex').resetPrefixSearch(): Promise<EnqueuedTask>
vectorStore
experimental feature to use it
client.index('myIndex').getEmbedders(): Promise<Embedders>
client.index('myIndex').updateEmbedders(embedders: Embedders): Promise<EnqueuedTask>
client.index('myIndex').resetEmbedders(): Promise<EnqueuedTask>
client.index('myIndex').getSearchCutoffMs(): Promise<SearchCutoffMs>
client.index('myIndex').updateSearchCutoffMs(searchCutoffMs: SearchCutoffMs): Promise<EnqueuedTask>
client.index('myIndex').resetSearchCutoffMs(): Promise<EnqueuedTask>
client.getKeys(parameters: KeysQuery): Promise<KeysResults>
client.getKey(keyOrUid: string): Promise<Key>
client.createKey(options: KeyCreation): Promise<Key>
client.updateKey(keyOrUid: string, options: KeyUpdate): Promise<Key>
client.deleteKey(keyOrUid: string): Promise<void>
client.isHealthy(): Promise<boolean>
client.health(): Promise<Health>
client.getStats(): Promise<Stats>
client.getVersion(): Promise<Version>
client.createDump(): Promise<EnqueuedTask>
client.createSnapshot(): Promise<EnqueuedTask>
Meilisearch provides and maintains many SDKs and integration tools like this one. We want to provide everyone with an amazing search experience for any kind of project. For a full overview of everything we create and maintain, take a look at the integration-guides repository.