Meilisearch & Typesense
Open-source search engines: instant search, typo tolerance, faceting, ranking.
meilisearchtypesensesearchbackend
# Meilisearch & Typesense
## Meilisearch
### Run
```bash
docker run -d --name meilisearch \
-p 7700:7700 \
-e MEILI_MASTER_KEY=masterKey \
getmeili/meilisearch:latest
```
### Node.js SDK
```bash
npm install meilisearch
```
```ts
import { MeiliSearch } from 'meilisearch'
const client = new MeiliSearch({ host: 'http://localhost:7700', apiKey: 'masterKey' })
const index = client.index('products')
// Add documents
await index.addDocuments([
{ id: 1, title: 'iPhone 15', brand: 'Apple', price: 799, tags: ['phone'] },
{ id: 2, title: 'Galaxy S24', brand: 'Samsung', price: 749, tags: ['phone'] },
])
// Search
const results = await index.search('iphone', {
limit: 10,
offset: 0,
filter: 'price < 1000 AND brand = Apple',
facets: ['brand', 'tags'],
attributesToHighlight: ['title'],
sort: ['price:asc'],
})
console.log(results.hits, results.facetDistribution)
```
### Configure settings
```ts
await index.updateSettings({
searchableAttributes: ['title', 'description', 'brand'], // order = relevance
filterableAttributes: ['brand', 'tags', 'price'],
sortableAttributes: ['price', 'rating'],
rankingRules: ['words', 'typo', 'proximity', 'attribute', 'sort', 'exactness'],
typoTolerance: { minWordSizeForTypos: { oneTypo: 4, twoTypos: 8 } },
synonyms: { 'smartphone': ['phone', 'mobile'], 'tv': ['television'] },
})
```
### React InstantSearch
```tsx
import { InstantSearch, SearchBox, Hits, RefinementList } from 'react-instantsearch'
import { instantMeiliSearch } from '@meilisearch/instant-meilisearch'
const searchClient = instantMeiliSearch('http://localhost:7700', 'searchKey')
<InstantSearch searchClient={searchClient} indexName="products">
<SearchBox />
<RefinementList attribute="brand" />
<Hits hitComponent={({ hit }) => <div>{hit.title}</div>} />
</InstantSearch>
```
---
## Typesense
### Run
```bash
docker run -d --name typesense \
-p 8108:8108 \
-v /tmp/typesense:/data \
typesense/typesense:26.0 \
--data-dir /data --api-key=xyz --enable-cors
```
### Node.js SDK
```ts
import Typesense from 'typesense'
const client = new Typesense.Client({
nodes: [{ host: 'localhost', port: 8108, protocol: 'http' }],
apiKey: 'xyz',
})
// Create collection (schema)
await client.collections().create({
name: 'products',
fields: [
{ name: 'title', type: 'string' },
{ name: 'brand', type: 'string', facet: true },
{ name: 'price', type: 'float', facet: true },
{ name: 'embedding', type: 'float[]', num_dim: 1536 }, // vector search
],
default_sorting_field: 'price',
})
// Search
const results = await client.collections('products').documents().search({
q: 'iphone',
query_by: 'title,brand',
filter_by: 'price:<1000',
facet_by: 'brand,price(ranges:[0,500],[500,1000])',
sort_by: 'price:asc',
per_page: 20,
})
```
## Choosing
| | Meilisearch | Typesense | Elasticsearch |
|---|---|---|---|
| Setup | Easy | Easy | Complex |
| Speed | Very fast | Very fast | Fast |
| Scale | Medium | Medium | Large |
| Vector search | Basic | Yes | Yes |
| Use case | Small-Medium apps | Small-Medium apps | Enterprise |API: /api/skills/meilisearch-typesense