MeiliSearch
Fast and relevant search engine. Instant search, typo tolerance, and multi-language support. Easy setup and developer-friendly.
Server
MeiliSearch
Overview
MeiliSearch is a blazingly fast and user-friendly open-source search engine built in Rust. Featuring sub-50 millisecond search speeds, AI-powered hybrid search, and typo tolerance, it delivers exceptional search experiences for both developers and end-users. As a self-hosted solution, businesses maintain complete control over their data.
Details
MeiliSearch 2024 edition provides next-generation search capabilities including AI-powered hybrid search that combines vector and keyword search, multi-modal search across images, videos, and audio, and multi-index search capabilities. Built with Rust's high-performance architecture, it achieves 50-millisecond search responses where traditional Elasticsearch takes 500+ milliseconds, featuring intuitive developer APIs and flexible self-hosted deployment options.
Key Features
- AI-Driven Search: Hybrid search combining semantic and full-text search capabilities
- High Performance: Sub-50 millisecond search response times
- Typo Tolerance: Returns relevant results even with spelling mistakes
- Multi-language Support: Comprehensive language support with language-specific optimizations
- Simple API: Developer-friendly RESTful API design
- Self-Hosted: Complete data control with flexible deployment options
Pros and Cons
Pros
- Easy setup with developer-friendly APIs providing high development efficiency
- Significantly faster search performance compared to Elasticsearch and Algolia
- Cost reduction and technical freedom through open-source nature
- Simple access to rich search features (facets, filtering, geosearch)
- Active community development and support
- Flexible pricing structure suitable for small to medium businesses
Cons
- Lacks the massive data processing capabilities of Elasticsearch
- Smaller plugin ecosystem compared to other mature search engines
- May underperform Elasticsearch in complex analytical queries
- Limited enterprise-grade features for large-scale deployments
- Restricted commercial support options
- May have limitations for certain advanced customization requirements
Reference Pages
- MeiliSearch Official Website
- MeiliSearch Documentation
- MeiliSearch GitHub Repository
- MeiliSearch API Reference
Code Examples
Setup and Installation
# Docker execution
docker run -it --rm \
-p 7700:7700 \
-v $(pwd)/meili_data:/meili_data \
getmeili/meilisearch:v1.5
# macOS installation (Homebrew)
brew install meilisearch
# Linux binary installation
curl -L https://install.meilisearch.com | sh
# Development environment startup
./meilisearch --master-key=yourMasterKey --db-path ./meili_data
# Docker Compose configuration
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
meilisearch:
image: getmeili/meilisearch:v1.5
ports:
- "7700:7700"
volumes:
- ./meili_data:/meili_data
environment:
- MEILI_MASTER_KEY=yourSecureMasterKey
- MEILI_DB_PATH=/meili_data
- MEILI_HTTP_ADDR=0.0.0.0:7700
- MEILI_LOG_LEVEL=INFO
restart: unless-stopped
EOF
docker-compose up -d
Index Creation and Document Management
# Create index
curl -X POST 'http://localhost:7700/indexes' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '{
"uid": "movies",
"primaryKey": "id"
}'
# Add single document
curl -X POST 'http://localhost:7700/indexes/movies/documents' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '{
"id": 1,
"title": "The Shawshank Redemption",
"overview": "Two imprisoned men bond over a number of years",
"genre": ["Drama", "Crime"],
"release_date": "1994-09-23",
"duration": 142,
"rating": 9.3,
"director": "Frank Darabont",
"studio": "Columbia Pictures"
}'
# Bulk add multiple documents
curl -X POST 'http://localhost:7700/indexes/movies/documents' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '[
{
"id": 2,
"title": "The Godfather",
"overview": "The aging patriarch of an organized crime dynasty transfers control",
"genre": ["Drama", "Crime"],
"release_date": "1972-03-24",
"duration": 175,
"rating": 9.2,
"director": "Francis Ford Coppola",
"studio": "Paramount Pictures"
},
{
"id": 3,
"title": "The Dark Knight",
"overview": "Batman begins his war on crime with his first major enemy being Jack Napier",
"genre": ["Action", "Crime", "Drama"],
"release_date": "2008-07-18",
"duration": 152,
"rating": 9.0,
"director": "Christopher Nolan",
"studio": "Warner Bros"
}
]'
# Bulk import from CSV file
curl -X POST 'http://localhost:7700/indexes/movies/documents' \
-H 'Content-Type: text/csv' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary @movies.csv
# Update document
curl -X PUT 'http://localhost:7700/indexes/movies/documents' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '{
"id": 1,
"rating": 9.4
}'
Search Query Implementation
# Basic search
curl -X POST 'http://localhost:7700/indexes/movies/search' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourSearchKey' \
--data-binary '{
"q": "batman"
}'
# Advanced search options
curl -X POST 'http://localhost:7700/indexes/movies/search' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourSearchKey' \
--data-binary '{
"q": "crime drama",
"attributesToRetrieve": ["id", "title", "overview", "rating"],
"attributesToHighlight": ["title", "overview"],
"attributesToCrop": ["overview"],
"cropLength": 15,
"filter": "genre = \"Crime\" AND rating > 8.5",
"sort": ["rating:desc", "release_date:desc"],
"facets": ["genre", "director", "studio"],
"limit": 20,
"offset": 0
}'
# Filtering search
curl -X POST 'http://localhost:7700/indexes/movies/search' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourSearchKey' \
--data-binary '{
"q": "",
"filter": "director = \"Christopher Nolan\" OR director = \"Francis Ford Coppola\"",
"facets": ["director", "studio", "genre"]
}'
# Geo search (location-based search)
curl -X POST 'http://localhost:7700/indexes/theaters/search' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourSearchKey' \
--data-binary '{
"q": "cinema",
"filter": "_geoRadius(40.7589, -73.9851, 5000)",
"sort": ["_geoPoint(40.7589, -73.9851):asc"]
}'
# Typo tolerance configuration
curl -X POST 'http://localhost:7700/indexes/movies/search' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourSearchKey' \
--data-binary '{
"q": "shawshenk redemtion",
"matchingStrategy": "all"
}'
Schema Design and Index Configuration
# Configure searchable attributes
curl -X PUT 'http://localhost:7700/indexes/movies/settings/searchable-attributes' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '[
"title",
"overview",
"director",
"genre"
]'
# Configure filterable attributes
curl -X PUT 'http://localhost:7700/indexes/movies/settings/filterable-attributes' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '[
"genre",
"director",
"studio",
"rating",
"release_date",
"_geo"
]'
# Configure sortable attributes
curl -X PUT 'http://localhost:7700/indexes/movies/settings/sortable-attributes' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '[
"rating",
"release_date",
"duration",
"title"
]'
# Configure ranking rules
curl -X PUT 'http://localhost:7700/indexes/movies/settings/ranking-rules' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '[
"words",
"typo",
"proximity",
"attribute",
"sort",
"exactness",
"rating:desc"
]'
# Configure synonyms
curl -X PUT 'http://localhost:7700/indexes/movies/settings/synonyms' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '{
"movie": ["film", "cinema", "picture"],
"director": ["filmmaker", "auteur"],
"action": ["adventure", "thriller"]
}'
# Configure typo tolerance
curl -X PUT 'http://localhost:7700/indexes/movies/settings/typo-tolerance' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '{
"enabled": true,
"minWordSizeForTypos": {
"oneTypo": 5,
"twoTypos": 9
},
"disableOnWords": ["Batman", "Nolan"],
"disableOnAttributes": ["director"]
}'
Performance Optimization
# Check index statistics
curl -X GET 'http://localhost:7700/indexes/movies/stats' \
-H 'Authorization: Bearer yourMasterKey'
# Monitor tasks
curl -X GET 'http://localhost:7700/tasks' \
-H 'Authorization: Bearer yourMasterKey'
# Optimize index settings
curl -X PUT 'http://localhost:7700/indexes/movies/settings' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '{
"pagination": {
"maxTotalHits": 10000
},
"faceting": {
"maxValuesPerFacet": 1000
},
"searchCutoffMs": 1500
}'
# Memory usage configuration (at startup)
export MEILI_MAX_INDEXING_MEMORY="2Gb"
export MEILI_MAX_INDEXING_THREADS=4
./meilisearch
# Production environment configuration
cat > meili.env << 'EOF'
MEILI_DB_PATH=/var/lib/meilisearch/data
MEILI_HTTP_ADDR=0.0.0.0:7700
MEILI_MASTER_KEY=yourProductionMasterKey
MEILI_ENV=production
MEILI_LOG_LEVEL=WARN
MEILI_MAX_INDEXING_MEMORY=4Gb
MEILI_MAX_INDEXING_THREADS=4
MEILI_EXPERIMENTAL_SEARCH_QUEUE_SIZE=2000
EOF
SDK and Framework Integration
// JavaScript/Node.js SDK
import { MeiliSearch } from 'meilisearch'
const client = new MeiliSearch({
host: 'http://localhost:7700',
apiKey: 'yourMasterKey'
})
// Create index
const index = await client.createIndex('movies', { primaryKey: 'id' })
// Add documents
const documents = [
{
id: 1,
title: 'The Shawshank Redemption',
overview: 'Two imprisoned men bond over a number of years',
genre: ['Drama', 'Crime'],
rating: 9.3
}
]
let task = await index.addDocuments(documents)
await index.waitForTask(task.taskUid)
// Perform search
const searchResults = await index.search('shawshank', {
attributesToHighlight: ['title', 'overview'],
filter: 'rating > 8.0',
sort: ['rating:desc'],
limit: 10
})
console.log(searchResults.hits)
// Advanced search configuration
await index.updateSettings({
searchableAttributes: ['title', 'overview', 'director'],
filterableAttributes: ['genre', 'rating', 'release_date'],
sortableAttributes: ['rating', 'release_date'],
synonyms: {
'movie': ['film', 'cinema', 'picture'],
'director': ['filmmaker', 'auteur']
}
})
# Python SDK
import meilisearch
client = meilisearch.Client('http://localhost:7700', 'yourMasterKey')
# Create index
index = client.create_index('movies', {'primaryKey': 'id'})
# Add documents
documents = [
{
'id': 1,
'title': 'The Shawshank Redemption',
'overview': 'Two imprisoned men bond over a number of years',
'genre': ['Drama', 'Crime'],
'rating': 9.3
}
]
task = index.add_documents(documents)
index.wait_for_task(task['taskUid'])
# Perform search
search_results = index.search('shawshank', {
'attributesToHighlight': ['title', 'overview'],
'filter': 'rating > 8.0',
'sort': ['rating:desc'],
'limit': 10
})
print(search_results['hits'])
# Update settings
index.update_settings({
'searchableAttributes': ['title', 'overview', 'director'],
'filterableAttributes': ['genre', 'rating', 'release_date'],
'sortableAttributes': ['rating', 'release_date'],
'synonyms': {
'movie': ['film', 'cinema', 'picture'],
'director': ['filmmaker', 'auteur']
}
})
Security and API Key Management
# Create API key
curl -X POST 'http://localhost:7700/keys' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '{
"description": "Search only key for production",
"actions": ["search"],
"indexes": ["movies"],
"expiresAt": "2024-12-31T23:59:59Z"
}'
# Create read-only key
curl -X POST 'http://localhost:7700/keys' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '{
"description": "Read-only key for analytics",
"actions": ["search", "documents.get", "indexes.get", "stats.get"],
"indexes": ["*"],
"expiresAt": null
}'
# Create admin key
curl -X POST 'http://localhost:7700/keys' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '{
"description": "Admin key for index management",
"actions": ["*"],
"indexes": ["movies", "users"],
"expiresAt": "2025-06-30T23:59:59Z"
}'
# List API keys
curl -X GET 'http://localhost:7700/keys' \
-H 'Authorization: Bearer yourMasterKey'
# SSL/TLS configuration (using Nginx)
cat > /etc/nginx/sites-available/meilisearch << 'EOF'
server {
listen 443 ssl http2;
server_name search.example.com;
ssl_certificate /path/to/ssl/certificate.crt;
ssl_certificate_key /path/to/ssl/private.key;
location / {
proxy_pass http://localhost:7700;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
EOF
Advanced Features and Hybrid Search
# Configure embedders for AI search
curl -X PUT 'http://localhost:7700/indexes/movies/settings/embedders' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourMasterKey' \
--data-binary '{
"huggingface": {
"source": "huggingFace",
"model": "sentence-transformers/all-MiniLM-L6-v2",
"revision": "main",
"documentTemplate": "{{doc.title}} {{doc.overview}}"
}
}'
# Perform hybrid search
curl -X POST 'http://localhost:7700/indexes/movies/search' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourSearchKey' \
--data-binary '{
"q": "space adventure movie",
"hybrid": {
"semanticRatio": 0.5,
"embedder": "huggingface"
},
"showRankingScore": true
}'
# Multi-index search
curl -X POST 'http://localhost:7700/multi-search' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourSearchKey' \
--data-binary '{
"queries": [
{
"indexUid": "movies",
"q": "action",
"limit": 5
},
{
"indexUid": "books",
"q": "thriller",
"limit": 5
}
]
}'
# Federated search
curl -X POST 'http://localhost:7700/indexes/global/search' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer yourSearchKey' \
--data-binary '{
"q": "science fiction",
"federation": {
"queries": [
{
"indexUid": "movies",
"weight": 0.8
},
{
"indexUid": "books",
"weight": 0.6
},
{
"indexUid": "games",
"weight": 0.4
}
]
}
}'
MeiliSearch is a modern search engine that prioritizes speed and simplicity, delivering exceptional performance especially for multi-language content including English and other international languages. It offers an excellent choice for achieving commercial-grade search functionality at low cost while leveraging the benefits of open-source software.