教程 / 后端集成 / 使用 Meilisearch 自托管搜索
📝 文字 ● 中级 更新于 2026-05-13

使用 Meilisearch 自托管搜索

Meilisearch 将 Algolia 的用户体验封装进了一个单一的 Rust 二进制文件。运行在 $5 VPS 上,通过 HTTP 建立索引,毫秒级查询响应。开源项目,使用与 Algolia 相同的 UI 组件库。

何时选择 Meilisearch

0
  • 选择 Meilisearch — 当你想以极低成本获得类 Algolia 的开发体验,或者数据不能离开自己的基础设施,又或者已经用完 Algolia 免费额度而不想开始付费时。
  • 选择 Algolia — 零运维,默认全球边缘节点。
  • 选择 Typesense ↗ — 与 Meilisearch 形态相同,但设计理念略有差异。
  • 选择 Postgres FTS — 如果记录数量少于约 10 万条,且搜索不是核心功能。

运行 Meilisearch 有两种方式:自托管(免费,自行维护服务器)或 Meilisearch Cloud ↗(付费,由官方托管)。本教程介绍自托管方案。

在本地运行 Meilisearch

1

单一二进制文件,一行命令启动:

curl -L https://install.meilisearch.com | sh
./meilisearch --master-key="your-strong-master-key"

监听 http://localhost:7700。生产环境必须设置 master key;不设置时 Meilisearch 以开发模式运行(无身份验证)。正式使用请生成一个足够长的随机字符串。

Docker 方式:

docker run -it --rm \
  -p 7700:7700 \
  -v $(pwd)/meili_data:/meili_data \
  getmeili/meilisearch:latest \
  meilisearch --master-key="your-strong-master-key"

验证是否正常运行:

curl http://localhost:7700/health
# {"status":"available"}

自托管官方文档 ↗

在生产 VPS 上运行

2

DigitalOceanHetzner 等平台开一台 $5/月的服务器,SSH 登录后执行:

# Install Meilisearch
curl -L https://install.meilisearch.com | sh
sudo mv ./meilisearch /usr/local/bin/

# Run as a systemd service
sudo nano /etc/systemd/system/meilisearch.service

粘贴以下内容:

[Unit]
Description=Meilisearch
After=systemd-user-sessions.service

[Service]
Type=simple
ExecStart=/usr/local/bin/meilisearch --config-file-path /etc/meilisearch.toml
Restart=on-failure

[Install]
WantedBy=multi-user.target

创建 /etc/meilisearch.toml,填入 master key、数据路径、运行环境等配置(参见 配置文档 ↗)。

sudo systemctl enable meilisearch
sudo systemctl start meilisearch

在前面加上 Nginx + HTTPS,你就拥有了一个真正可用的搜索端点:https://search.yourdomain.com

创建 API 密钥

3

master key 仅用于管理员操作,不要在应用中直接使用。请为应用创建权限受限的 API 密钥。

首次启动时会自动生成两个默认密钥,用 master key 查询 keys 接口获取:

curl -X GET 'http://localhost:7700/keys' \
  -H 'Authorization: Bearer your-master-key'

两个默认密钥:

  • Default Admin API Key — 完整读写权限,仅限后端使用。
  • Default Search API Key — 仅搜索权限,可安全用于浏览器端。
MEILI_HOST=https://search.yourdomain.com
MEILI_MASTER_KEY=your-master-key                # backend admin ops only
MEILI_ADMIN_KEY=xxxxxxxxxx                      # backend; from Default Admin API Key
MEILI_SEARCH_KEY=xxxxxxxxxx                     # safe for client; from Default Search API Key

安装 SDK

为第一批记录建立索引

5
import { MeiliSearch } from "meilisearch";

const client = new MeiliSearch({
  host: process.env.MEILI_HOST,
  apiKey: process.env.MEILI_ADMIN_KEY,
});

// Add documents (creates the index automatically)
await client.index("posts").addDocuments([
  {
    id: 1,                                    // required; primary key
    title: "How to deploy to Vercel",
    body: "First, install the CLI...",
    tags: ["deploy", "vercel"],
    published_at: 1714521600,
  },
  { id: 2, title: "...", body: "..." },
]);

Meilisearch 异步处理文档,返回一个任务 ID。批量导入数百万条记录时,可轮询 /tasks/{id} 确认完成状态。少量添加时,数据通常在毫秒内即可搜索。

配置索引

6

最常用的两类设置(与 Algolia 概念相同):

// Which fields are searchable, in priority order
await client.index("posts").updateSearchableAttributes([
  "title",
  "body",
  "tags",
]);

// Which fields you can filter on
await client.index("posts").updateFilterableAttributes(["tags", "author"]);

// Custom ranking
await client.index("posts").updateRankingRules([
  "words", "typo", "proximity", "attribute",
  "sort", "exactness",
  "published_at:desc",       // newer first
]);

设置文档 ↗

从浏览器发起搜索

7
import { MeiliSearch } from "meilisearch";

const client = new MeiliSearch({
  host: process.env.NEXT_PUBLIC_MEILI_HOST,
  apiKey: process.env.NEXT_PUBLIC_MEILI_SEARCH_KEY,    // search-only; safe
});

const results = await client.index("posts").search("vercel", {
  limit: 10,
  filter: ['tags = "deploy"'],
});

使用仅搜索密钥。该密钥只能读取,不能修改数据,可以安全地放到浏览器端。

引入 UI 组件库

8

Meilisearch 提供了与 InstantSearch 兼容的适配器,所有 Algolia UI 组件都可以直接使用:

npm install instantsearch.js @meilisearch/instant-meilisearch
# or for React:
npm install react-instantsearch @meilisearch/instant-meilisearch
import { InstantSearch, SearchBox, Hits } from "react-instantsearch";
import { instantMeiliSearch } from "@meilisearch/instant-meilisearch";

const { searchClient } = instantMeiliSearch(
  process.env.NEXT_PUBLIC_MEILI_HOST,
  process.env.NEXT_PUBLIC_MEILI_SEARCH_KEY,
);

export function Search() {
  return (
    <InstantSearch searchClient={searchClient} indexName="posts">
      <SearchBox />
      <Hits hitComponent={({ hit }) => <div>{hit.title}</div>} />
    </InstantSearch>
  );
}

instant-meilisearch ↗

将数据库同步到 Meilisearch

9

与 Algolia 的同步模式相同:

  • 每次写入时同步 — 写数据库的同时调用 addDocuments。实现简单,但会略微增加写延迟。
  • 通过 Inngest 异步同步 — 数据库写入后触发事件,由函数负责同步到 Meilisearch。解耦,更健壮。
  • 定期批量同步 — 每隔 N 分钟同步所有变更记录。实现最简单,但存在小段数据延迟窗口。

对于 Postgres → Meilisearch 的同步,Airbyte ↗ 提供免费的连接器。如果你使用 Supabase,也可以直接使用 Supabase 的 Meilisearch Wrapper ↗

常用操作

10
// Update (merges with existing fields by primary key)
await client.index("posts").updateDocuments([
  { id: 1, body: "Updated body" },
]);

// Delete
await client.index("posts").deleteDocument(1);
await client.index("posts").deleteDocuments({ filter: 'tags = "draft"' });

// Stats
const stats = await client.index("posts").getStats();
console.log(stats.numberOfDocuments);

// Drop the whole index
await client.deleteIndex("posts");

备份

11

Meilisearch 会生成一个单独的 dump 文件,可用于恢复数据:

curl -X POST 'http://localhost:7700/dumps' \
  -H 'Authorization: Bearer your-master-key'

dump 文件保存在配置的数据目录中。可通过 cron 定期触发,再用 rsync 同步到 S3 / R2 进行异地备份。恢复时,在启动 Meilisearch 时加上 --import-dump path/to/dump.dump 参数即可。

Meilisearch 可以在几分钟内从源数据库重建索引——对很多团队来说,"数据库就是备份,发生故障时重新同步到 Meilisearch"的方案已经足够。

如果自托管太繁琐,可使用 Meilisearch Cloud

12

Meilisearch Cloud ↗ 托管的是与自托管完全相同的引擎。入门套餐 $30/月。如果你不想维护一台 Linux 服务器,这是值得的选择;在相当规模下,费用仍远低于 Algolia。

迁移是对称的——从自托管导出 dump,恢复到 Cloud,再更新客户端的 host URL 即可。

切勿在没有身份验证的情况下暴露 Meilisearch。不设置 master key 时,任何能访问到你端口的人都可以读取并清空你的索引。生产环境务必使用强 master key。建议绑定 localhost 并在前面放 Nginx,或在防火墙层面限制客户端 IP。

官方参考资料

下一步