先说下我的背景,我需要对一个文件表(es存了一份),查询某个文件的下级。
实现方法是根据filePath和level一起查询,如果是mysql可以用 file_path like '父文件路径%' 这种方式实现。
但是我需要用 ES实现,查了一下有 wildcard 能实现同样的功能。
先看下我的索引数据
我的问题,很简单,如 搜索
/测试项目12
开头的所有数据
1、先创建索引
这里贴出完整的内容
"settings": {
"index": {
"number_of_shards": "1",
"number_of_replicas": "1"
"index.max_ngram_diff": 5,
"analysis": {
"analyzer": {
"ngram_analyzer": {
"tokenizer": "ngram_tokenizer"
"tokenizer": {
"ngram_tokenizer": {
"type": "ngram",
"min_gram": 1,
"max_gram": 5,
"token_chars": [
"letter",
"digit"
"mappings": {
"properties": {
"repoPrefix": {
"type": "keyword"
"fileName": {
"type": "text",
"analyzer": "ngram_analyzer"
"level": {
"type": "long"
"leafFlag": {
"type": "boolean"
"filePath": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
"text": {
"type": "text",
"analyzer": "ngram_analyzer"
"creatorName": {
"type": "text"
"description": {
"type": "text"
"updateTime": {
"type": "date"
"revision": {
"type": "long"
"createTime": {
"type": "date"
"fileSize": {
"type": "long"
"updaterName": {
"type": "text"
"_class": {
"type": "keyword"
"id": {
"type": "long"
"projectId": {
"type": "long"
"fileType": {
"type": "long"
主要看 filePath那段
2、wildcard模糊查询语句
指定使用 keyword 类型
GET http://10.1.5.190:9200/common_file/_search
"query": {
"wildcard": {
"filePath.keyword": "/测试项目12*"
运行结果如下
成功查出来了,不容易啊!!!
3. 使用分词查询
因为我还需要用这个字段分词查询,比如查询任意一段内容,比如 查询 12/历史库/v1 ,一般的分词器是满足不了,所以用到了ngram_tokenizer分词器
使用 text 类型
GET http://10.1.5.190:9200/common_file/_search
"query": {
"match": {
"filePath.text": "12/历史库/v1"
运行结果如下
三、完整的代码实现
这里贴出我的需求,根据文件名称/路径搜索,且能满足搜索指定文件夹下面的文件(根据仓库路径,文件路径右匹配和level一起查询)
//查询对象
BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
// level查询
if (CommonUtil.isNotEmpty(fileSearchDTO.getLevel()))
queryBuilder.must(QueryBuilders.matchQuery("level", fileSearchDTO.getLevel()+1));
// repoPrefix查询
if (CommonUtil.isNotEmpty(fileSearchDTO.getRepoPrefix()))
queryBuilder.must(QueryBuilders.matchQuery("repoPrefix", fileSearchDTO.getRepoPrefix()));
// filePath查询
if (CommonUtil.isNotEmpty(fileSearchDTO.getFilePath()))
queryBuilder.must(QueryBuilders.wildcardQuery("filePath.keyword", fileSearchDTO.getFilePath()+"*"));
// 关键字查询
// 搜文件路径
if ("filePath".equals(fileSearchDTO.getSearchType()))
queryBuilder.must(QueryBuilders.matchQuery("filePath.text", fileSearchDTO.getSearchKeywords()));
// 搜文件名称
queryBuilder.must(QueryBuilders.matchQuery("fileName", fileSearchDTO.getSearchKeywords()));
PageRequest pageRequest = PageRequest.of(fileSearchDTO.getPage() - 1, fileSearchDTO.getLimit());
org.springframework.data.domain.Page<EsCommonFile> esCommonFilePage = esCommonFileRepository.search(queryBuilder, pageRequest);