简介
Meilisearch 是一个开源的轻量级全文搜索引擎,支持中文分词、模糊搜索、拼写纠错等。
与之相似的竞品有:Elasticsearch、Typesense、Algolia等。其中,Elasticsearch 是老牌搜索服务,但是运行起来太笨重了,除非数据量很大,否则其余轻量级的实现要更好。
后两者 Typesense、Algolia 和本文的主角 Meilisearch 都是更轻量级别的存在,但是 Algolia 不开源,只能使用他们的云服务,而我不太喜欢被平台给局限住,所以也放弃了。
Typesense 和 Meilisearch 都是开源的同时也都提供云服务。很可惜,前者的文档集存在 RAM 里,后者则主要放在磁盘里,虽然性能上确实是前者更出色,但是很明显 RAM 可比存储空间贵的多。
另外,Meilisearch 的社区开发环境也更好。截至本文发布,Meilisearch 有52K stars, 296 watching, 2.1K forks, 201 contributors
,而 Typesense 只有23.6K stars, 132 watching, 773 forks, 46 contributors
。
(另外,Meilisearch还是用我喜欢的Rust写的)
因此,本文主要讲 Meilisearch 的部署与使用。另附我找到的几个比较资料,或许能帮你选择合适自己的服务。
- Algolia vs ElasticSearch vs Meilisearch vs Typesense 之比较 | 日思录
- Meilisearch 与 Typesense - Meilisearch 搜索引擎
部署
Meilisearch 支持下载二进制和 Docker 部署两种方式。
二进制
另外,Meilisearch 还支持一键脚本安装:
curl -L https://install.meilisearch.com | sh
或者手动下载二进制文件:
Releases · meilisearch/meilisearch
下载完后,使用以下方式启动:
./meilisearch --master-key=YourMasterKey
其中,MasterKey 算是一个管理员密码,可以是 16 位以上的 UTF-8 字符串。获取 API 密钥需要通过此Key,访问管理后台也需要。
也可以自定义端口,默认是7700。
./meilisearch --http-addr '0.0.0.0:7700'
Docker
docker run -it --rm \
-p 7700:7700 \
getmeili/meilisearch \
meilisearch --master-key='YourMasterKey' --http-addr '0.0.0.0:7700'
使用
使用也很简单,分4步,分别是查看当前的API Token、设置要搜索的数据类型、写入数据、搜索。 下面会用到很多curl,windows建议用Postman,直接粘贴进去就能解析。
查看当前API Token
curl -X GET 'https://Your_Meili_URL/keys' -H 'Authorization: YourMasterToken'
获取到的结果是:
{
"results": [
{
"name": "Default Search API Key",
"description": "Use it to search from the frontend",
"key": "xxxxxxxx",
"uid": "xxxxxxxx",
"actions": [
"search"
],
"indexes": [
"*"
],
"expiresAt": null,
"createdAt": "2025-06-25T11:08:45.729263258Z",
"updatedAt": "2025-06-25T11:08:45.729263258Z"
},
{
"name": "Default Admin API Key",
"description": "Use it for anything that is not a search operation. Caution! Do not expose it on a public frontend",
"key": "xxxxxxxx",
"uid": "xxxxxxxx",
"actions": [
"*"
],
"indexes": [
"*"
],
"expiresAt": null,
"createdAt": "2025-06-25T11:08:45.726891008Z",
"updatedAt": "2025-06-25T11:08:45.726891008Z"
}
],
"offset": 0,
"limit": 20,
"total": 2
}
简单来说会给你两个 Token,存在key字段里,上面是搜索用的,下面是管理用的。
设置数据类型
如果你想索引这样的一个东西:
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(50)
content String @db.VarChar(200)
userUid Int?
createdAt DateTime @default(now())
User User? @relation(fields: [userUid], references: [uid])
}
它包含一个主键:id
,两个你想索引的东西:title
,content
。
那么,你首先应该创建这个项:
(这里的API Token既可以用MasterKey,也能用Default Admin API Key)
curl -X POST 'https://Your_Meili_URL/indexes' \
-H 'Authorization: Bearer API_TOKEN' \
-H 'Content-Type: application/json' \
--data '{
"uid": "posts",
"primaryKey": "id"
}'
结果:
{
"taskUid": 0,
"indexUid": "posts",
"status": "enqueued",
"type": "indexCreation",
"enqueuedAt": "2025-06-25T12:37:59.414437837Z"
}
然后,设置可被搜索的字段:
curl -X PUT 'https://Your_Meili_URL/indexes/posts/settings/searchable-attributes' \
-H 'Authorization: Bearer API_KEY' \
-H 'Content-Type: application/json' \
--data '[
"title", "content"
]'
你也可以设置一些可以用于排序的字段:
curl -X PUT 'https://Your_Meili_URL/indexes/posts/settings/sortable-attributes' \
-H 'Authorization: Bearer API_KEY' \
-H 'Content-Type: application/json' \
--data '["createdAt"]'
类似的,设置用于过滤的字段:
curl -X PUT 'https://Your_Meili_URL/indexes/posts/settings/filterable-attributes' \
-H 'Authorization: Bearer API_KEY' \
-H 'Content-Type: application/json' \
--data '["userUid"]'
写入数据
现在就可以写入数据了。可以用curl,或者是官方SDK:
curl -X POST 'https://Your_Meili_URL/indexes/posts/documents' \
-H 'Authorization: Bearer API_KEY' \
-H 'Content-Type: application/json' \
--data '[
{
"id": 1,
"createdAt": "2025-06-25T00:00:00Z",
"title": "中文标题",
"content": "中文内容",
"userUid": 1,
}
]'
import { MeiliSearch } from 'meilisearch';
import { Post } from '@/generated/prisma';
const client = new MeiliSearch({
host: process.env.MEILI_HOST || "",
apiKey: process.env.MEILI_API_KEY,
})
const index = client.index('posts')
async function addSingleDocument(post: Post) {
await index.addDocuments([post])
}
await addSingleDocument(post)
搜索
搜索也是,可以用curl,或者是官方SDK:
参数 | 说明 |
---|---|
q | 要搜索的关键词 |
limit | 返回的最大结果数 |
offset | 跳过的结果数(用于分页) |
filter | 过滤条件(可选) |
sort | 排序条件(可选) |
curl -X POST 'https://Your_Meili_URL/indexes/posts/search' \
-H 'Authorization: Bearer API_KEY' \
-H 'Content-Type: application/json' \
--data '{
"q": "关键词",
"limit": 10,
"offset": 0,
"filter": "userUid = 1 AND title = xxx",
"sort": ["createdAt:desc"]
}'
import { MeiliSearch } from 'meilisearch';
const client = new MeiliSearch({
host: process.env.MEILI_HOST || "",
apiKey: process.env.MEILI_API_KEY,
})
async function searchPosts(query) {
const index = client.index('posts')
const result = await index.search(query, {
limit: 10
})
console.log(result.hits)
}
searchPosts('中文')