文章目录
springboot整合es
引入pom
<dependence>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</dependence>
<dependence>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependence>
application.properties配置
spring.elasticsearch.rest.uris=ip地址
spring.elasticsearch.rest.username=username
spring.elasticsearch.rest.password=password
查询流程
//1、创建SearchRequest对象,设置索引可通过构造参数,或者调用 searchRequest.indices("索引名称", "索引名称2")
SearchRequest searchRequest = new SearchRequest("索引名称");
//2、创建BoolQueryBuilder对象 可通过new或以下方式
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//3、通过QueryBuilders创建一系列条件对象 如模糊查询
FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("字段名称", param);
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("字段名称", param);
//4、通过boolQueryBuilder连接条件 可通过must【相当于and】 should【相当于or】
boolQueryBuilder.must(fuzzyQueryBuilder).must(termQueryBuilder);
//5、创建SearchSourceBuilder对象
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//6、设置查询的boolQueryBuilder条件
searchSourceBuilder.query(boolQueryBuilder);
//7、searchRequest设置source
searchRequest.source(searchSourceBuilder);
//8、通过restHighLevelClient进行查询,得到SearchReqponse对象 spring可通过@AutoWaire注入
RestHighLevelClient client = new RestHightClient();
SearchResponse searchResponse = client.search(searchRequest, RequestOption.DEFAULT);
/**
* 9、拿到命中数据 可通过searchHits.totalHit 查询总命中条数 searchHits.length查看实际返回条数
* 注:当数据量巨大的时候,es会默认分页
*/
searchHits searchHits = searchResponse.getHits();
SearchHit[] hits = searchHits.getHits();
// 10、遍历hits 封装数据到自定义实体类ResultVo中,注意映射字段名称要对应
List<ResultVO> resultVoList = new ResultVo;
for(SearchHit hit : hits){
Map<String, Object> hitSourceMap = hit.getSourceAsMap;//得到查询的map数据
//通过com.alibaba.fastjson.JSONObject将map转化为json,然后映射到实体类中
ResultVo vo = JSONObject.parseObject(JSONObject.toJSONString(hitSourceMao), ResultVo.class);
resultVoList.add(vo);
}
System.out.println("查询结果" + resultVoList);
常用查询介绍
1.termQuery 精确查询
term: 这种查询和match在有些时候是等价的,比如我们查询单个的词hello,那 么会和match查询结果一样,但是如果查询"helloworld",结果就相差很大,因 为这个输入不会进行分词,就是说查询的时候,是查询字段分词结果中是否 有"helloworld"的字样,而不是查询字段中包含"hello world"的字样。当保存 数据"helloworld"时,elasticsearch会对字段内容进行分词,“hello world"会 被分成hello和world,不存在"helloworld”,因此这里的查询结果会为空。这也 是term查询和match的区别。
代码:
BoolQueryBuilder queryBoolBuilder = QueryBuilders.boolQuery();
queryBoolBuilder.termQuery("es数据字段名称", param);
//多字段匹配 类似于in (param1, param2, ...)
queryBoolBuilder.termsQuery("es数据字段名称", param1, param2)
2.模糊查询、match查询
-
fuzzy:模糊查询
例如数据:
"hits":[ { "_source":{ "title": "你好" } }, { "_source":{ "title": "好呀1" } }, { "_source":{ "title": "你好啊" } } ]
GET /_search { "query": { "fuzzy" : { "title" : "你好呀" } } } 搜索结果:好呀1 你好啊
由于查询词和索引词之间的编辑距离为1【允许错1个字】,此时是可以召回文档的。
参数名 含义 fuzziness 定义最大的编辑距离,默认为AUTO,即按照es的默认配置。
fuzziness可选的值为0,1,2,也就是说编辑距离最大只能设置为2。
AUTO策略:在AUTO模式下,es将根据输入查询的term的长度决定编辑距离大小。用户也可以自定义term长度边界的最大和最小值,AUTO:[low],[high],如果没有定义的话,默认值为3和6,即等价于 AUTO:3,6,即按照以下方案:
0-2:必须精确匹配
3-5:编辑距离为1
5:编辑距离为2prefix_length 定义最初始不会被“模糊”的term的数量。这是基于用户的输入一般不会在最开始犯错误的设定的基础上设置的参数。这个参数的设定将减少去召回限定编辑距离的的term时,检索的term的数量。默认参数为0。 max_expansions 定义fuzzy query会扩展的最大term的数量。默认为50. transpositions 定义在计算编辑聚利时,是否允许term的交换(例如ab->ba),实际上,如果设置为true的话,计算的就是Damerau,F,J distance。默认参数为false。 详细文档地址 https://www.elastic.co/guide/en/elasticsearch/guide/current/fuzzy-query.html -
wildCardQuery:模糊查询[当传入参数过长,会导致查询失效]
通过通配符
- *:表示多个字符(0或多个)
- ?:表示单个字符 【不可匹配中文—>1个字两个字符】
QueryBuilders .wildCardQuery("es数据字段名称", param);
{ "query": { "bool": { "must": [ "wildcard": { "字段名称": "?44*" } ] } } } 可能匹配到的值:244 2445 544 6444243432 注:中文时,不加通配符和 * + param + * 效果和param一样
-
match_phase:会对输入做分词,但是需要结果中也包含所有的分词,而且顺序要 求一样。以"helloworld"为例,要求结果中必须包含hello和world,而且还要求 他们是连着的,顺序也是固定的,hello thatword不满足,world hello也不满 足条件。
代码:
QueryBuilders.matchPhraseQuery("es数据字段名称", param);
-
match:部分匹配的模糊查询,和match_phase类似,但是匹配中不要求顺序一致。会将查询的词汇进行分词,比如中国【中、国】,可能匹配到的词如 中华、国家。
QueryBuilders.matchQuery("es数据字段名称", param);
-
match_phrase_prefix:前缀查询,根据短语中最后一个词组做前缀匹配,可以应用于搜索提示,但注意和max_expanions搭配。其实默认是50
QueryBuilders.matchPhrasePrefixQuery("es数据字段名称", param);
-
match_all:查询全部。
QueryBuilders.matchAllQuery();
-
multi_match:多字段查询,使用相当的灵活,可以完成match_phrase和match_phrase_prefix的工作。
QueryBuilders.ultiMathQuery(param, "es数据字段名称", "es数据字段名称2", ...);
3.嵌套查询 nestedQuery
例如要查询concatNumber = “15398432399” 且 concatType = “01” 的数据。
//es中数据
"_source":{
"kid": "543234535",
//二级嵌套 path路径:bp (后面会说到)
"bp":[
{
"name": "chamu"
}
],
"cust":[
{
"custId": "43243242",
"concat": {//三级嵌套 path路径:cust.concat
"concatType": "01",//未分词
"concatNumber": "15398432399" //分词
}
}
]
}
查看es中字段是否分词,可通过Get请求 http://ip地址/索引名/_mapping 查看该索引数据结构
嵌套精确查询时,若查询词汇在数据结构上未设置分词,使用termQuery【分词后精确查询查不到】,设置了分词则使用matchParseQuery【分词匹配,分词后要求匹配的顺序相同】
例:查询concatNumber = "15398432399" 且 concatType = "01"。此处path路径为cust.concat
//另外创建一个BoolQueryBuilder
BoolQueryBuilder builder = QueryBuilders.boolQuery();
builder.must(QueryBuilder.termQuery("path路径.contactType", "01"));
builder.must(QueryBuilder.matchPaseQuery("path路径.concatNumber", "15398432399"));
NestedQueryBuilder nestedQueryBuilder = queryBoolBuider.nestedQuery("path路径", builder, Socore.None);
boolQueryBuilder.must(nestedQueryBuilder);
注:
QueryBuilder.matchPaseQuery("path路径.concatNumber", "15398432399");
可使用matchQuery,可用以下语句替换 测试效果一样
QueryBuilder.matchQUery("path路径.concatNumber", "15398432399").operator(Operator.AND);