ElasticSearch ES wildcard实现模糊查询和Java整合使用

avatar 2021年12月08日09:45:51 6 9917 views
博主分享免费Java教学视频,B站账号:Java刘哥 ,长期提供技术问题解决、项目定制:本站商品点此

昨天下班前弄了一下 wildcard 模糊查询发现没有效果,今天早上来马上就解决了,记录下。

说明:查询的字段必须有keyword类型

 

需求背景

先说下我的背景,我需要对一个文件表(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()));

}
// 搜文件名称
else
{
	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);

 

 

 

  • 微信
  • 交流学习,资料分享
  • weinxin
  • 个人淘宝
  • 店铺名:言曌博客咨询部

  • (部分商品未及时上架淘宝)
avatar

发表评论

avatar 登录者:匿名
匿名评论,评论回复后会有邮件通知

  

已通过评论:0   待审核评论数:0