Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

meilisearch

meilisearch504.4kMIT0.50.0TypeScript support: included

The Meilisearch JS client for Node.js and the browser.

meilisearch, search, instant, relevant, client, wrapper, meili

readme

Meilisearch-JavaScript

Meilisearch JavaScript

Meilisearch | Meilisearch Cloud | Documentation | Discord | Roadmap | Website | FAQ

npm version Tests Codecov Prettier License Merge Queues enabled

⚡ 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.

Table of Contents

📖 Documentation

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.

🔧 Installation

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.

Run Meilisearch

⚡️ 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.

Import

After installing meilisearch-js, you must import it into your application. There are many ways of doing that depending on your development environment.

<summary>

⚠️ If any issues arise importing meilisearch/token

</summary>

[!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

import syntax

Usage in an ES module environment:

import { MeiliSearch } from "meilisearch";

const client = new MeiliSearch({
  host: "http://127.0.0.1:7700",
  apiKey: "masterKey",
});

<script> tag

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.

require syntax

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",
});

React Native

To use meilisearch-js with React Native, you must also install react-native-url-polyfill.

Deno

Usage in a Deno environment:

import { MeiliSearch } from "npm:meilisearch";

const client = new MeiliSearch({
  host: "http://127.0.0.1:7700",
  apiKey: "masterKey",
});

🚀 Getting started

Take a look at the playground for a concrete example.

Add documents

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.

Basic search

// 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"
}

Using search parameters

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"
}

Custom search with filters

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

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.

Abortable search

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()

Using Meilisearch behind a proxy

Custom request config

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'
  }
})

Custom http client

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
  }
})

🤖 Compatibility with Meilisearch

This package guarantees compatibility with version v1.x of Meilisearch, but some features may not be present. Please check the issues for more info.

💡 Learn more

The following sections in our main documentation website may interest you:

This repository also contains more examples.

⚙️ Contributing

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.

📜 API resources

Search

Make a search request

client.index<T>('xxx').search(query: string, options: SearchParams = {}, config?: Partial<Request>): Promise<SearchResponse<T>>

Make a search request using the GET method (slower than the search method)

client.index<T>('xxx').searchGet(query: string, options: SearchParams = {}, config?: Partial<Request>): Promise<SearchResponse<T>>

Make multiple search requests

client.multiSearch(queries?: MultiSearchParams, config?: Partial<Request>): Promise<Promise<MultiSearchResponse<T>>>

multiSearch uses the POST method when performing its request to Meilisearch.

Search For Facet Values

Search for facet values

client.index<T>('myIndex').searchForFacetValues(params: SearchForFacetValuesParams, config?: Partial<Request>): Promise<SearchForFacetValuesResponse>

Documents

Add or replace multiple documents

client.index('myIndex').addDocuments(documents: Document<T>[]): Promise<EnqueuedTask>

Add or replace multiple documents in string format

client.index('myIndex').addDocumentsFromString(documents: string, contentType: ContentType, queryParams: RawDocumentAdditionOptions): Promise<EnqueuedTask>

Add or replace multiple documents in batches

client.index('myIndex').addDocumentsInBatches(documents: Document<T>[], batchSize = 1000): Promise<EnqueuedTask[]>

Add or update multiple documents

client.index('myIndex').updateDocuments(documents: Array<Document<Partial<T>>>): Promise<EnqueuedTask>

Add or update multiple documents in string format

client.index('myIndex').updateDocumentsFromString(documents: string, contentType: ContentType, queryParams: RawDocumentAdditionOptions): Promise<EnqueuedTask>

Add or update multiple documents in batches

client.index('myIndex').updateDocumentsInBatches(documents: Array<Document<Partial<T>>>, batchSize = 1000): Promise<EnqueuedTask[]>

Get Documents

client.index.getDocuments(parameters: DocumentsQuery = {}): Promise<DocumentsResults<T>>>

Get one document

client.index('myIndex').getDocument(documentId: string): Promise<Document<T>>

Delete one document

client.index('myIndex').deleteDocument(documentId: string | number): Promise<EnqueuedTask>

Delete multiple documents

client.index('myIndex').deleteDocuments(params: DocumentsDeletionQuery | DocumentsIds): Promise<EnqueuedTask>

Delete all documents

client.index('myIndex').deleteAllDocuments(): Promise<Types.EnqueuedTask>

Tasks

Get all tasks

client.getTasks(parameters: TasksQuery): Promise<TasksResults>

Get one task

client.getTask(uid: number): Promise<Task>

Delete tasks

client.deleteTasks(parameters: DeleteTasksQuery = {}): Promise<EnqueuedTask>

Cancel tasks

client.cancelTasks(parameters: CancelTasksQuery = {}): Promise<EnqueuedTask>

Get all tasks of an index

client.index('myIndex').getTasks(parameters: TasksQuery): Promise<TasksResults>

Get one task of an index

client.index('myIndex').getTask(uid: number): Promise<Task>

Wait for one task

client.tasks.waitForTask(uid: number, { timeout?: number, interval?: number }): Promise<Task>

Wait for multiple tasks

client.tasks.waitForTasks(uids: number[], { timeout?: number, interval?: number }): Promise<Task[]>

Batches

Get one batch

client.getBatch(uid: number): Promise<Batch>

Get all batches

client.getBatches(parameters: BatchesQuery = {}): Promise<BatchesResults>

Indexes

Get all indexes in Index instances

client.getIndexes(parameters: IndexesQuery): Promise<IndexesResults<Index[]>>

Get all indexes

client.getRawIndexes(parameters: IndexesQuery): Promise<IndexesResults<IndexObject[]>>

Create a new index

client.createIndex<T>(uid: string, options?: IndexOptions): Promise<EnqueuedTask>

Create a local reference to an index

client.index<T>(uid: string): Index<T>

Get an index instance completed with information fetched from Meilisearch

client.getIndex<T>(uid: string): Promise<Index<T>>

Get the raw index JSON response from Meilisearch

client.getRawIndex(uid: string): Promise<IndexObject>

Get an object with information about the index

client.index('myIndex').getRawInfo(): Promise<IndexObject>

Update Index

Using the client
client.updateIndex(uid: string, options: IndexOptions): Promise<EnqueuedTask>
Using the index object
client.index('myIndex').update(data: IndexOptions): Promise<EnqueuedTask>

Delete index

Using the client
client.deleteIndex(uid): Promise<void>
Using the index object
client.index('myIndex').delete(): Promise<void>

Get specific index stats

client.index('myIndex').getStats(): Promise<IndexStats>
Return Index instance with updated information
client.index('myIndex').fetchInfo(): Promise<Index>
Get Primary Key of an Index
client.index('myIndex').fetchPrimaryKey(): Promise<string | undefined>
Swap two indexes
client.swapIndexes(params: SwapIndexesParams): Promise<EnqueuedTask>

Settings

Get settings

client.index('myIndex').getSettings(): Promise<Settings>

Update settings

client.index('myIndex').updateSettings(settings: Settings): Promise<EnqueuedTask>

Reset settings

client.index('myIndex').resetSettings(): Promise<EnqueuedTask>

Pagination Settings

Get pagination

client.index('myIndex').getPagination(): Promise<PaginationSettings>

Update pagination

client.index('myIndex').updatePagination(pagination: PaginationSettings): Promise<EnqueuedTask>

Reset pagination

client.index('myIndex').resetPagination(): Promise<EnqueuedTask>

Synonyms

Get synonyms

client.index('myIndex').getSynonyms(): Promise<Synonyms>

Update synonyms

client.index('myIndex').updateSynonyms(synonyms: Synonyms): Promise<EnqueuedTask>

Reset synonyms

client.index('myIndex').resetSynonyms(): Promise<EnqueuedTask>

Stop words

Get stop words

client.index('myIndex').getStopWords(): Promise<string[]>

Update stop words

client.index('myIndex').updateStopWords(stopWords: string[] | null ): Promise<EnqueuedTask>

Reset stop words

client.index('myIndex').resetStopWords(): Promise<EnqueuedTask>

Ranking rules

Get ranking rules

client.index('myIndex').getRankingRules(): Promise<string[]>

Update ranking rules

client.index('myIndex').updateRankingRules(rankingRules: string[] | null): Promise<EnqueuedTask>

Reset ranking rules

client.index('myIndex').resetRankingRules(): Promise<EnqueuedTask>

Distinct Attribute

Get distinct attribute

client.index('myIndex').getDistinctAttribute(): Promise<string | void>

Update distinct attribute

client.index('myIndex').updateDistinctAttribute(distinctAttribute: string | null): Promise<EnqueuedTask>

Reset distinct attribute

client.index('myIndex').resetDistinctAttribute(): Promise<EnqueuedTask>

Searchable attributes

Get searchable attributes

client.index('myIndex').getSearchableAttributes(): Promise<string[]>

Update searchable attributes

client.index('myIndex').updateSearchableAttributes(searchableAttributes: string[] | null): Promise<EnqueuedTask>

Reset searchable attributes

client.index('myIndex').resetSearchableAttributes(): Promise<EnqueuedTask>

Displayed attributes

Get displayed attributes

client.index('myIndex').getDisplayedAttributes(): Promise<string[]>

Update displayed attributes

client.index('myIndex').updateDisplayedAttributes(displayedAttributes: string[] | null): Promise<EnqueuedTask>

Reset displayed attributes

client.index('myIndex').resetDisplayedAttributes(): Promise<EnqueuedTask>

Filterable attributes

Get filterable attributes

client.index('myIndex').getFilterableAttributes(): Promise<string[]>

Update filterable attributes

client.index('myIndex').updateFilterableAttributes(filterableAttributes: string[] | null): Promise<EnqueuedTask>

Reset filterable attributes

client.index('myIndex').resetFilterableAttributes(): Promise<EnqueuedTask>

Sortable attributes

Get sortable attributes

client.index('myIndex').getSortableAttributes(): Promise<string[]>

Update sortable attributes

client.index('myIndex').updateSortableAttributes(sortableAttributes: string[] | null): Promise<EnqueuedTask>

Reset sortable attributes

client.index('myIndex').resetSortableAttributes(): Promise<EnqueuedTask>

Faceting

Get faceting

client.index('myIndex').getFaceting(): Promise<Faceting>

Update faceting

client.index('myIndex').updateFaceting(faceting: Faceting): Promise<EnqueuedTask>

Reset faceting

client.index('myIndex').resetFaceting(): Promise<EnqueuedTask>

Typo tolerance

Get typo tolerance

client.index('myIndex').getTypoTolerance(): Promise<TypoTolerance>

Update typo tolerance

client.index('myIndex').updateTypoTolerance(typoTolerance: TypoTolerance | null): Promise<EnqueuedTask>

Reset typo tolerance

client.index('myIndex').resetTypoTolerance(): Promise<EnqueuedTask>

Separator tokens

Get separator tokens

client.index('myIndex').getSeparatorTokens(): Promise<SeparatorTokens>

Update separator tokens

client.index('myIndex').updateSeparatorTokens(separatorTokens: SeparatorTokens | null): Promise<EnqueuedTask>

Reset separator tokens

client.index('myIndex').resetSeparatorTokens(): Promise<EnqueuedTask>

Non Separator tokens

Get non separator tokens

client.index('myIndex').getNonSeparatorTokens(): Promise<NonSeparatorTokens>

Update non separator tokens

client.index('myIndex').updateNonSeparatorTokens(nonSeparatorTokens: NonSeparatorTokens | null): Promise<EnqueuedTask>

Reset non separator tokens

client.index('myIndex').resetNonSeparatorTokens(): Promise<EnqueuedTask>

Dictionary

Get dictionary

client.index('myIndex').getDictionary(): Promise<Dictionary>

Update dictionary

client.index('myIndex').updateDictionary(dictionary: Dictionary | null): Promise<EnqueuedTask>

Reset dictionary

client.index('myIndex').resetDictionary(): Promise<EnqueuedTask>

Proximity Precision

Get proximity precision

client.index('myIndex').getProximityPrecision(): Promise<ProximityPrecision>

Update proximity precision

client.index('myIndex').updateProximityPrecision(proximityPrecision: ProximityPrecision): Promise<EnqueuedTask>

Reset proximity precision

client.index('myIndex').resetProximityPrecision(): Promise<EnqueuedTask>

Facet search settings

Get facet search settings

client.index('myIndex').getFacetSearch(): Promise<boolean>

Update facet search settings

client.index('myIndex').updateFacetSearch(enabled: boolean): Promise<EnqueuedTask>

Reset facet search settings

client.index('myIndex').resetFacetSearch(): Promise<EnqueuedTask>

Prefix search settings

Get prefix search settings

client.index('myIndex').getPrefixSearch(): Promise<PrefixSearch>

Update prefix search settings

client.index('myIndex').updatePrefixSearch(prefixSearch: PrefixSearch): Promise<EnqueuedTask>

Reset prefix search settings

client.index('myIndex').resetPrefixSearch(): Promise<EnqueuedTask>

Embedders

Get embedders

client.index('myIndex').getEmbedders(): Promise<Embedders>

Update embedders

client.index('myIndex').updateEmbedders(embedders: Embedders): Promise<EnqueuedTask>

Reset embedders

client.index('myIndex').resetEmbedders(): Promise<EnqueuedTask>

SearchCutoffMs

Get SearchCutoffMs

client.index('myIndex').getSearchCutoffMs(): Promise<SearchCutoffMs>

Update SearchCutoffMs

client.index('myIndex').updateSearchCutoffMs(searchCutoffMs: SearchCutoffMs): Promise<EnqueuedTask>

Reset SearchCutoffMs

client.index('myIndex').resetSearchCutoffMs(): Promise<EnqueuedTask>

Keys

Get keys

client.getKeys(parameters: KeysQuery): Promise<KeysResults>

Get one key

client.getKey(keyOrUid: string): Promise<Key>

Create a key

client.createKey(options: KeyCreation): Promise<Key>

Update a key

client.updateKey(keyOrUid: string, options: KeyUpdate): Promise<Key>

Delete a key

client.deleteKey(keyOrUid: string): Promise<void>

isHealthy

Return true or false depending on the health of the server

client.isHealthy(): Promise<boolean>

Health

Check if the server is healthy

client.health(): Promise<Health>

Stats

Get database stats

client.getStats(): Promise<Stats>

Version

Get binary version

client.getVersion(): Promise<Version>

Dumps

Trigger a dump creation process

client.createDump(): Promise<EnqueuedTask>

Snapshots

Trigger a snapshot on-demand process

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.