摘要:本文主要介绍meilisearch
的安装和简单使用。安装采用docker
部署,案例与SpringBoot3
结合,并展示了我们平常业务中会遇到的场景的使用案例。
meilisearch
与elasticsearch
对比
1. 定位与核心目标
特性 | MeiliSearch | Elasticsearch |
---|---|---|
定位 | 轻量级、易用的全文搜索引擎,强调简单性和快速启动。 | 企业级搜索与分析引擎,支持复杂搜索、实时分析和大数据处理。 |
目标用户 | 开发者、初创团队、小型项目或内部工具。 | 中大型企业、需要复杂搜索和数据分析的场景(如日志、监控、电商)。 |
2. 架构与部署
特性 | MeiliSearch | Elasticsearch |
---|---|---|
架构 | 单节点为主,集群支持较简单。 | 分布式架构,天生支持分片(Shard)和副本(Replica),适合横向扩展。 |
部署复杂度 | 一键安装,依赖少,资源占用低。 | 需要 Java 环境,配置复杂,运维成本高。 |
扩展性 | 扩展性有限,适合中小规模数据。 | 支持动态扩缩容,适合海量数据和高并发场景。 |
3. 查询与功能
特性 | MeiliSearch | Elasticsearch |
---|---|---|
查询语法 | 简单 API,类似 RESTful,学习成本低。 | 复杂的 DSL(Domain-Specific Language),功能强大但学习曲线陡峭。 |
搜索模式 | 实时索引,支持模糊搜索、拼写纠正、同义词等基础功能。 | 支持聚合分析、地理搜索、模糊匹配、高亮等高级功能。 |
自定义功能 | 插件生态较少,扩展性有限。 | 丰富的插件生态(如中文分词器 IK、拼音分词),支持脚本和自定义分析器。 |
4. 性能与资源消耗
特性 | MeiliSearch | Elasticsearch |
---|---|---|
资源消耗 | 内存和 CPU 占用低,适合轻量级应用。 | 资源消耗较高,尤其是大数据量时需优化 JVM 和分片策略。 |
实时性 | 近实时(默认 1 秒刷新),适合一般场景。 | 近实时(默认 1 秒),支持更细粒度的刷新控制。 |
写入速度 | 较快,适合中小规模数据写入。 | 高吞吐写入,支持批量操作和复杂流水线处理。 |
安装
meilisearch
安装
docker-compose.yml
,挂载了数据出来
yaml
services:
meilisearch:
image: getmeili/meilisearch:v1.14
container_name: meilisearch
environment:
MEILI_MASTER_KEY: meilisearch_master
ports:
- 7700:7700
volumes:
- ./meili_data:/meili_data
环境变量说明
MEILI_MASTER_KEY
: 相当于token
,调用的秘钥,设计比较简单。
meilisearch-ui
安装
该可视化工具只能在内网中使用,不能暴露到公网。
yaml
services:
meilisearch-ui:
image: riccoxie/meilisearch-ui:lite
container_name: meilisearch-ui
ports:
- 24900:24900

与springboot
集成使用
pom.xml
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.meilisearch.sdk</groupId>
<artifactId>meilisearch-java</artifactId>
<version>0.14.4</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.31</version>
</dependency>
</dependencies>
application.yml
yaml
meilisearch:
host-url: http://192.168.137.131:7700
master-key: meilisearch_master
MeilisearchProperties
typescript
@Data
public class MeilisearchProperties {
private String hostUrl;
private String masterKey;
}
MeilisearchConfig
typescript
@Configuration
public class MeilisearchConfig {
@Bean
@ConfigurationProperties(prefix = "meilisearch")
public MeilisearchProperties meilisearchProperties(){
return new MeilisearchProperties();
}
@Bean
public Client meilisearchClient(MeilisearchProperties meilisearchProperties){
return new Client(new Config(meilisearchProperties.getHostUrl(), meilisearchProperties.getMasterKey()));
}
}
Goods
定义的存储实体
vbnet
@Data
public class Goods {
private Long id;
private String name;
private String desc;
private String score;
private Long paid;
}
GoodsService
typescript
@Service
public class GoodsService {
@Autowired
private Client client;
/**
* 新增或编辑内容
* @param goodsList
*/
public void add(List<Goods> goodsList){
Index index = client.index("goods");
index.addDocuments(JSON.toJSONString(goodsList));
}
/**
* 简单搜索
* @param search
* @return
*/
public SearchResult search(String search){
Index index = client.index("goods");
return index.search(search);
}
/**
* 高亮搜索
* @param search
* @return
*/
public Searchable search2(String search){
SearchRequest searchRequest = new SearchRequest(search);
searchRequest.setShowMatchesPosition(true);
searchRequest.setAttributesToHighlight(new String[] {"name"});
Index index = client.index("goods");
return index.search(searchRequest);
}
/**
* 带过滤条件的搜索
* @param search
* @return
*/
public Searchable search3(String search){
SearchRequest searchRequest = new SearchRequest(search);
searchRequest.setShowMatchesPosition(true);
searchRequest.setAttributesToHighlight(new String[] {"name"});
searchRequest.setFilter(new String[] {"id > 1 AND name = Action"});
Index index = client.index("goods");
index.updateFilterableAttributesSettings(new String[]
{
"id",
"name"
});
return index.search(searchRequest);
}
/**
* 自定义评分搜索
* @param search
* @return
*/
public Searchable search4(String search){
Index index = client.index("goods");
index.updateSortableAttributesSettings(new String[] {"score"});
index.updateRankingRulesSettings(new String[]{
"paid:desc",
"words",
"typo",
"proximity",
"attribute",
"sort",
"exactness"}
);
SearchRequest searchRequest = new SearchRequest(search);
searchRequest.setShowRankingScore(true);
//searchRequest.setSort(new String[]{"score:desc"});
return index.search(searchRequest);
}
}
GoodsController
入口控制器
typescript
@RestController
@RequestMapping(value = "goods")
public class GoodsController {
@Autowired
public GoodsService goodsService;
@Autowired
private Client client;
@GetMapping("createIndex")
public Object createIndex(String index){
client.createIndex(index, "id");
client.getIndex(index).updateFilterableAttributesSettings(new String[]{ "id", "name", "age"});
client.getIndex(index).updateRankingRulesSettings(new String[] {});
return "success";
}
@PostMapping(value = "add")
public Object add(@RequestBody List<Goods> goodsList){
goodsService.add(goodsList);
return "success";
}
@GetMapping(value = "search")
public Object search(String search) {
return goodsService.search(search);
}
@GetMapping(value = "search2")
public Object search2(String search) {
return goodsService.search2(search);
}
@GetMapping(value = "search3")
public Object search3(String search) {
return goodsService.search3(search);
}
@GetMapping(value = "search4")
public Object search4(String search) {
return goodsService.search4(search);
}
}
实际场景案例
电商搜索案例
电商搜索一般都有价格区间查询,价格排序,销量排序,所以我们就要把评分标准的判断
sort
提前,一般提到第一个。
- 配置
arduino
Index index = client.index("goods");
index.updateSortableAttributesSettings(new String[] {"score"});
index.updateRankingRulesSettings(new String[]{
"sort",
"words",
"typo",
"proximity",
"attribute",
"exactness"}
);
- 查询
ini
SearchRequest searchRequest = new SearchRequest(search);
searchRequest.setShowRankingScore(true);
searchRequest.setSort(new String[]{"score:desc"});
return index.search(searchRequest);
知识库搜索案例
就默认的排序即可,完全按照权重数据来排序