搜索结果处理
排序
elasticsearch支持对搜索结果排序,默认是根据相关度算分(_score)来排序。可以排序字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等。
GET /indexName/_search
{
"query":{
"match_all":{}
},
"sort":[
{
"FIELD":"desc" //排序字段和排序方式ASC、DESC 升序、降序
}
]
}
GET /indexName/_search
{
"query":{
"match_all":{}
},
"sort":[
{
"_geo_distance":{
"FIELD":"纬度,经度",
"order":"asc",
"unit":"km" //单位
}
}
]
}
GET /hotel/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"score": {
"order": "desc"
},
"price": {
"order": "asc"
}
}
]
}
GET /hotel/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"_geo_distance": {
"location": {
"lat": 31,
"lon": 121
},
"order": "asc",
"unit": "km"
}
}
]
}
分页
elasticsearch默认情况下只返回top10的数据。而如果要查询更多的数据就需要修改分页参数了。
elasticsearch中通过修改from、size参数来控制要返回的分页结果
GET /hotel/_search
{
"query":{
"match_all":{}
},
"from":990, //分页开始的位置,默认为0
"size":10, //期望获取的文档总数
"sort":[
{
"price":"asc"
}
]
}
GET /hotel/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"price":"asc"
}
],
"from": 0,
"size": 20
}
深度分页问题
ES是分布式的,所以会面临深度分页问题。例如price排序后,获取from=990,size=10的数据:
高亮处理
高亮:就是在搜索结果中把搜索关键字突出显示。
GET /hotel/_search
{
"query":{
"match":{
"FIELD":"TEXT" //不能为match_all{} 因为高亮一定是对某个字段进行高亮
}
},
"highlight":{
"fields":{ //高亮的字段不止一个
"FIELD":{
"pre_tags":"<em>", //用于标记高亮字段的前置标签
"post_tags":"</em>" //用于标记高亮字段的后置标签
}
}
}
}
GET /hotel/_search
{
"query": {
"match": {
"all": "如家"
}
},
"highlight": {
"fields": {
"name": {
"require_field_match": "false",
"pre_tags": "<em>",
"post_tags": "</em>"
}
}
}
}
RestClient查询文档
match_all
void testMatchAll() throws IOException {
//1.准备Request
SearchRequest request=new SearchRequest("hotel");
//2.准备DSL
request.source().query(QueryBuilders.matchAllQuery());
//3.发送请求
SearchResponse search = client.search(request, RequestOptions.DEFAULT);
System.out.println(search);
}
void testMatchAll() throws IOException {
//1.准备Request
SearchRequest request=new SearchRequest("hotel");
//2.准备DSL
request.source().query(QueryBuilders.matchAllQuery());
//3.发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//解析结果
SearchHits hits = response.getHits();
//查询的总条数
long total = hits.getTotalHits().value;
System.out.println("一共搜索到 "+total+"数据");
//查询hit数组
SearchHit[] hits1 = hits.getHits();
//遍历hit数组
for(SearchHit hit : hits1){
//得到source
String json=hit.getSourceAsString();
//反序列化
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
//打印
System.out.println(hotelDoc);
System.out.println();
}
}
全文检索查询
全文检索的match和multi_match查询与match_all的API基本一致。差别是查询条件,也就是query部分。
multi_match
:对多个字段进行查询。
void testMulMatchAll() throws IOException {
//创建request
SearchRequest request=new SearchRequest("hotel");
//准备DSL
SearchSourceBuilder query = request.source().query(QueryBuilders.matchQuery("all", "如家"));
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
TotalHits totalHits = hits.getTotalHits();
System.out.println("搜索到的数据一共有:"+totalHits+"条");
SearchHit[] hits1 = hits.getHits();
for(SearchHit hit : hits1){
String json = hit.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
System.out.println();
}
}
void testMulMatchAll1() throws IOException {
//创建request
SearchRequest request=new SearchRequest("hotel");
//准备DSL
SearchSourceBuilder query = request.source().query(QueryBuilders.multiMatchQuery("如家","brand","name","business"));
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
TotalHits totalHits = hits.getTotalHits();
System.out.println("搜索到的数据一共有:"+totalHits+"条");
SearchHit[] hits1 = hits.getHits();
for(SearchHit hit : hits1){
String json = hit.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
System.out.println();
}
}
精确查询
void BooleanMatch() throws IOException {
//1.准备Request
SearchRequest request=new SearchRequest("hotel");
//准备DSL
//准备BooleanQuery
BoolQueryBuilder boolQuery=QueryBuilders.boolQuery();
//添加term
boolQuery.must(QueryBuilders.termQuery("city","北京"));
boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));
request.source().query(boolQuery);
//发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
TotalHits totalHits = hits.getTotalHits();
System.out.println("搜索到的数据一共有:"+totalHits+"条");
SearchHit[] hits1 = hits.getHits();
for(SearchHit hit : hits1){
String json = hit.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
System.out.println();
}
}
排序和分页
void PageTest() throws IOException {
//1.准备Request
SearchRequest request=new SearchRequest("hotel");
//准备DSL
//准备query
request.source().query(QueryBuilders.matchAllQuery());
//排序
request.source().sort("price", SortOrder.ASC);
//分页
request.source().from(0).size(5);
//发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
TotalHits totalHits = hits.getTotalHits();
System.out.println("搜索到的数据一共有:"+totalHits+"条");
SearchHit[] hits1 = hits.getHits();
for(SearchHit hit : hits1){
String json = hit.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
System.out.println();
}
}
高亮
void HighLightTest() throws IOException {
//1.准备Request
SearchRequest request=new SearchRequest("hotel");
//准备DSL
//准备query
request.source().query(QueryBuilders.matchQuery("all","如家"));
//高亮
request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
//发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
TotalHits totalHits = hits.getTotalHits();
System.out.println("搜索到的数据一共有:"+totalHits+"条");
SearchHit[] hits1 = hits.getHits();
for(SearchHit hit : hits1){
String json = hit.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
System.out.println();
}
}
但是为什么没有出现高亮呢?
void HighLightTest1() throws IOException {
//1.准备Request
SearchRequest request=new SearchRequest("hotel");
//准备DSL
//准备query
request.source().query(QueryBuilders.matchQuery("all","如家"));
//高亮
request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
//发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
TotalHits totalHits = hits.getTotalHits();
System.out.println("搜索到的数据一共有:"+totalHits+"条");
SearchHit[] hits1 = hits.getHits();
for(SearchHit hit : hits1){
//获取高亮结果
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
//根据字段名获取高亮结果
HighlightField highlightField = highlightFields.get("name");
if(highlightField!=null){
//获取高亮值
String string = highlightField.getFragments()[0].string();
System.out.println(string);
}
}
}
加粗样式