Files
blog-press/docs/Web/Others/Meilisearch.md
2026-08-16 17:21:36 +08:00

6.6 KiB
Raw Blame History

title, date
title date
Meilisearch简介和使用 2026-08-15

一、简介

Meilisearch 是一个基于 Rust 构建的开源全文搜索引擎,面向“用户侧搜索体验”设计。通过 REST API 接收 JSON 文档并建立倒排索引,提供 sub50ms 的搜索响应、默认拼写容错、前缀搜索、相关度排序与过滤分面能力,适用于站内搜索、商品检索、文档/知识库搜索、Cmd+K、RAG 检索层等场景。

二、核心概念

概念 说明
Index索引 一组共享设置的文档集合,等价于“表”,如 productsarticles
Document文档 JSON 对象,是搜索基本单位,必须包含主键
Primary Key主键 文档唯一标识,默认推断 id相同主键写入即覆盖upsert
Task任务 所有写操作异步执行,返回 taskUid状态enqueued → processing → succeeded / failed
Settings Index 级配置searchable / filterable / sortable / displayed attributes、ranking rules、synonyms、stop words、tokenizer
Ranking Rules 默认相关度规则:words → typo → proximity → attribute → sort → exactness,可定制
Master Key 实例级最高密钥≥16 bytes用于生成其他 Key禁止下发前端
API Key Search / Admin / Read-Only Admin / Chat按 action + index 粒度授权
Tenant Token 由 API Key 派生,搜索时注入 filter实现多租户行级隔离
Embedder 内建向量化配置,支持 OpenAI / HuggingFace / Ollama / Cohere / 自定义 REST用于 Hybrid Search

三、与Elasticsearch比较

维度 Meilisearch Elasticsearch
核心引擎 Rust + LMDBmmap单机 ACID Java + Apache Lucenedistributed
部署形态 单进程 / 单容器 多节点集群shard + replica + 选主)
查询延迟 sub-50ms 默认(前缀/typo 开箱) sub-100ms200ms需调优达到极低 P99
索引吞吐 中(异步 task 队列,单机受限) bulk + 多 shard 并行)
近实时性 亚秒级 task 完成即可见 refresh_interval 默认 1s
内存占用 ~200MB 空闲,无 GC 12GB+ 起JVM heap 调优关键
横向扩展 社区版单节点Cloud/企业版支持 shard+replica 原生分片、副本、跨集群复制
规模上限 单机百万~千万文档(索引通常 < 100GB 级) PB 级、百亿~千亿文档
聚合分析 facet 计数级 完整 aggregation / pipeline / SIEM
分词/相关度 内置 Charabia + 默认 ranking 显式 analyzer / DSL / fuzziness 调优
运维复杂度 低(启容器+key+dump heap/shard/ILM/TLS/RBAC
成本模型 单机 $1020/月级 托管最小集群 $150+/月级
许可证 MIT CE / BUSL-1.1 AGPL / SSPL / ELv2

四、Docker安装

services:
  meilisearch:
    image: getmeili/meilisearch:v1.16
    container_name: meilisearch
    restart: unless-stopped
    ports:
      - "7700:7700"
    environment:
      MEILI_MASTER_KEY: key
    volumes:
      - ./meili_data:/meili_data
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:7700/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 20s
    networks:
      - meili-net

  meilisearch-ui:
    image: eyeix/meilisearch-ui:v0.15.1-lite
    container_name: meilisearch-ui
    restart: unless-stopped
    ports:
      - "24900:24900"
    environment:
      TZ: Asia/Shanghai
    depends_on:
      meilisearch:
        condition: service_healthy
    networks:
      - meili-net

networks:
  meili-net:
    driver: bridge

启动后在浏览器中打开ip:24900新增实例和索引。

五、SpringBoot集成

5.1 安装依赖

<dependency>
    <groupId>com.meilisearch.sdk</groupId>
    <artifactId>meilisearch-java</artifactId>
    <version>0.20.0</version>
</dependency>

::: warning 该版本需要okhttp 4.12版本如有冲突需要指定okhttp版本

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.12.0</version>
</dependency>

:::

5.2 配置属性

meilisearch:
  host: http:/ip:7700
  api-key: key

5.3 配置类

@Configuration
@ConfigurationProperties(prefix = "meilisearch")
@Data
public class MeiliSearchConfig {
    private String host;
    private String apiKey;

    @Bean
    public Client meiliClient() {
        return new Client(new Config(host, apiKey));
    }
}

5.4 操作实例

@Service
public class MeiliSearchServiceImpl implements MeiliSearchService {
    @Resource
    private Client meiliClient;

    @Override
    public <T> int addDocuments(String indexUid, List<T> documents) {
        String jsonArray = JSONUtil.toJsonStr(documents);
        TaskInfo taskInfo = meiliClient.index(indexUid).addDocuments(jsonArray);
        meiliClient.waitForTask(taskInfo.getTaskUid());
        return taskInfo.getTaskUid();
    }

    @Override
    public void updateDocument(String indexUid, Object document) {
        TaskInfo task = meiliClient.index(indexUid).updateDocuments(JSONUtil.toJsonStr(document));
        meiliClient.waitForTask(task.getTaskUid());
    }

    @Override
    public void deleteDocument(String indexUid, String documentId) {
        TaskInfo task = meiliClient.index(indexUid).deleteDocument(documentId);
        meiliClient.waitForTask(task.getTaskUid());
    }

    @Override
    public SearchResult search(String indexUid, String query, List<String> highlightFields) {
        SearchRequest request = new SearchRequest(query)
                .setShowMatchesPosition(true)
                .setAttributesToHighlight(highlightFields.toArray(new String[0]));
        return (SearchResult) meiliClient.index(indexUid).search(request);
    }
}

::: tip 这里如果开启高亮搜索会有个bugMeilisearch ApiException: {Error=APIError: {message='Invalid value type at .attributesToHighlight: expected an array, but found a string: "**[Ljava.lang.String;@10fc5e2f**"', code='invalid_search_attributes_to_highlight', type='invalid_request',
解决方案:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>com.vaadin.external.google</groupId>
            <artifactId>android-json</artifactId>
        </exclusion>
    </exclusions>
</dependency>

参考:issue :::