DSL查询语法和RestClient查询文档

news2024/11/27 15:28:11

目录

DSL查询语法

DLS Query的分类

DSL Query基本语法 

全文检索查询

精准查询

地理查询

复合查询

Function Score Query

复合查询 Boolean Query

搜索结果处理

排序

分页

分页

深度分页问题 

深度分也解决方案

高亮

RestClient查询文档

快速入门

全文检索查询

精准查询

复合查询

排序、分页

高亮 

案例

搜索和查询

结果过滤

周边

竞价排名


查询DSL的基本语法是什么?
GET/索引库名/_search
{ "query": { "查询类型":{ "FIELD": "TET"}}}


match和multi_match的区别是什么?

1、match:根据一个字段查询
2、multi_match:根据多个字段查询,参与查询字段越多,查询性能越差


精确查询常见的有哪些?
1、term查询:根据词条精确匹配,一般搜索keyword类型、数值类型、布尔类型、日期类型字段
2、range查询:根据数值范围查询,可以是数值、日期的范围


elasticsearch中的相关性打分算法是什么?
1、TF-IDF:在elasticsearch5.0之前,会随着词频增加而越来越大
2、BM25:在elasticsearch5.0之后,会随着词频增加而增大,但增长曲线会趋于水平


function score query定义的三要素是什么?
1、过滤条件:哪些文档要加分
2、算分函数:如何计算function score
3、加权方式:function score 与query score如何运算


bool查询有几种逻辑关系?
1、must:必须匹配的条件,可以理解为“与”
2、should:选择性匹配的条件,可以理解为“或”
3、must_not:必须不匹配的条件,不参与打分
4、filter:必须匹配的条件,不参与打分


from + size:

1、优点:支持随机翻页
2、缺点:深度分页问题,默认查询上限(from + size)是10000

3、场景:百度、京东、谷歌、淘宝这样的随机翻页搜索
after search:
1、优点:没有查询上限(单次查询的size不超过10000)

2、缺点:只能向后逐页查询,不支持随机翻页
3、场景:没有随机翻页需求的搜索,例如手机向下滚动翻页

scroll:
1、优点:没有查询上限(单次查询的size不超过10000 )

2、缺点:会有额外内存消耗,并且搜索结果是非实时的
3、场景:海量数据的获取和迁移。从ES7.1开始不推荐,建议用aftersearch方案。


查询的基本步骤是:
1、创建SearchRequest对象
2、准备Request.source(),也就是DSL。
2.1、QueryBuilders来构建查询条件
2.2、传入Request.source()的query()方法

3、发送请求,得到结果
4、解析结果(参考JSON结果,从外到内,逐层解析)


要构建查询条件,只要记住一个类:QueryBuilders


1、所有搜索DSL的构建,记住一个API:SearchRequest的source()方法。
2、高亮结果解析是参考JSON结果,逐层解析

DSL查询语法

DLS Query的分类

Elasticsearch提供了基于JSON的DSL (Domain Specific Language)来定义查询。

常见的查询

查询所有:查询出所有数据,一般测试用。例如: match_all
全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。

例如:
1、match_query
2、multi_match_query
精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。

例如:
1、ids
2、range

3、term
地理(geo)查询:根据经纬度查询。

例如∶
1、geo_distance
2、geo_bounding_box
复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。

例如;
1、bool
2、function_score

DSL Query基本语法 

GET /hotel/_search
{
  "query": {
    "match_all": {}
  }
}

全文检索查询

match查询:全文检索查询的一种,会对用户输入内容分词,然后去倒排索引库检索

GET /hotel/_search
{
  "query": {
    "match": {
      "all": "外滩如家"
    }
  }
}

因为外滩如家可以分词为:外滩、如家。所以可以查询到包含着两个词之一的内容 

multi_match: 与match查询类似,只不过允许同时查询多个字段

GET /hotel/_search
{
  "query": {
    "multi_match": {
      "query": "外滩如家",
      "fields": ["brand","name","business"]
    }
  }
}

查询brand,name,business之一包含外滩、如家之一的内容

精准查询

精确查询一般是查找keyword、数值、日期、boolean等类型字段。所以不会对搜索条件分词

term查询:根据词条精准值查询

GET /hotel/_search
{
  "query": {
    "term": {
      "city": {
        "value": "上海"
      }
    }
  }
}

city中必须为上海,包含“上海”但是不只有这两个字也不能查询到

range查询:根据值的范围查询

GET /hotel/_search
{
  "query": {
    "range": {
        "price": {
          "gte": 1008,
          "lte": 3000
      }
    }
  }
}

price大于等于100,小于等于300 。没有e就是没有等于

地理查询

根据经纬度查询

geo bounding box:查询geo_point值落在某个矩形范围的所有文档

GET /indexName/_search
{
  "query": {
    "geo_bounding_box": {
       "FIELD": {
         "top_left": {
           "lat": 31.1,
           "lon": 121.5
         },
         "bottom_right": {
           "lat": 30.9,
           "lon": 121.7
         }
       }
    }
  }
}

geo_distance:查询到指定中心点小于某个距离值的所有文档

GET /hotel/_search
{
  "query": {
    "geo_distance": {
        "distance": "1km",
        "location": "31.21, 121.5"
    }
  }
}

查询到的都是距离31.21,121.5不超过1km的内容 

复合查询

复合(compound)查询:复合查询可以将其它简单查询组合起来,实现更复杂的搜索逻辑

fuction score:算分函数查询,可以控制文档相关性算分,控制文档排名

当我们利用match查询时,文档结果会根据与搜索词条的关联度打分(_score),返回结果时按照分值降序排列

Function Score Query

使用function score query,可以修改文档的相关性算分(query score),根据新得到的算分排序。

原始查询条件,搜索文档并根据相关性打分(query score)

"query": {
    "match": {
            "all": "外滩"
          }
        },

过滤条件,符合条件的文档才会被重新算分

"filter": {
            "term": {
              "id": "1"
            }
          }, 

算分函数,算分函数的结果称为function score ,将来会与queryscore运算,得到新算分

常见的算分函数有:
1、weight:给一个常量值,作为函数结果(function score)

2、field_value_factor:用文档中的某个字段值作为函数结果

3、random_score:随机生成一个值,作为函数结果
4、script_score:自定义计算公式,公式结果作为函数结果

"weight": 10 

加权模式,定义function score与query score的运算方式

包括:

1、multiply:两者相乘。默认就是这个
2、replace:用function score替换query score

3、其它: sum、avg、max、min

"boost_mode": "mutliply" 

GET /hotel/_search
{
  "query": {
    "function_score": {
        "query": {
          "match": {
            "all": "外滩"
          }
        },
        "functions": [
          {
          "filter": {
            "term": {
              "brand": "如家"
            }
          },
          "weight": 10
          }
        ],
        "boost_mode": "sum"
    }
  }
}

满足条件的内容权重会+10,使得它会在更前面 

复合查询 Boolean Query

布尔查询是一个或多个查询子句的组合

子查询的组合方式有:

1、must:必须匹配每个子查询,类似“与”
2、should:选择性匹配子查询,类似“或”
3、must_not:必须不匹配,不参与算分,类似“非”

4、filter:必须匹配,不参与算分

GET /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "如家"
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "gt": 400
            }
          }
        }
      ],
      "filter": [
        {
          "geo_distance": {
            "distance": "10km",
            "location": {
              "lat": 31.21,
              "lon": 121.5
            }
          }
        }
      ]
    }
  }
}

name必须为“如家”,价格必须不大于400,地理在31.21,121.5不超过10km的内容

搜索结果处理

排序

 elasticsearch支持对搜索结果排序,默认是根据相关度算分(_score)来排序

可以排序字段类型有::keyword类型、数值类型、地理坐标类型、日期类型等

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "score": "desc"
    },
    {
      "price": "asc"
    }
  ]
}

先根据score降序,再根据price升序 

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 31.034661,
          "lon": 121.612282
        },
        "order": "asc",
        "unit": "km"
      }
    }
  ]
}

找到121.612282,31.034661周围的酒店,距离升序排序,单位为km

分页

分页

elasticsearch默认情况下只返回top10的数据。而如果要查询更多数据就需要修改分页参数了

elasticsearch中通过修改from、size参数来控制要返回的分页结果

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "price": "asc"
    }
  ],
  "from": 0,
  "size": 10
}

从第0页开始,每页10个。所以这里查到的是前10个 

深度分页问题 

ES是分布式的,所以会面临深度分页问题。

1、首先在每个数据分片上都排序并查询前1000条文档。
2、然后将所有节点的结果聚合,在内存中重新排序选出前1000条文档
3、最后从这1000条中,选取从990开始的10条文档
如果搜索页数过深,或者结果集(from + size)越大,对内存和CPU的消耗也越高。

因此ES设定结果集查询的上限是10000

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "price": "asc"
    }
  ],
  "from": 9991,
  "size": 10
}

从9991页开始,每页10个,则会查到第10001个数据。报错

深度分也解决方案

针对深度分页,ES提供了两种解决方案

1、search after:分页时需要排序,原理是从上一次的排序值开始,查询下一页数据。官方推荐使用的方式。

2、scroll:原理将排序数据形成快照,保存在内存。官方已经不推荐使用。

高亮

高亮:就是在搜索结果中把搜索关键字突出显示。

原理是这样的:
1、将搜索结果中的关键字用标签标记出来

2、在页面中给标签添加css样式

默认情况下,搜索字段必须与高亮字段一致才能高亮。

这里的"require_field_match": "false",就让搜索字段不需要与高亮字段一致也能高亮

GET /hotel/_search
{
  "query": {
    "match": {
      "all": "如家"
    }
  },
  "highlight": {
    "fields": {
      "name": {
        "require_field_match": "false"
      }
    }
  }
}

name为“如家”的位置加上了css的高亮标签了。源部分不会有高亮标签,highlight才部分才有高亮标签

RestClient查询文档

hotel-demo和sqlhttps://pan.baidu.com/s/10SEnZ93I2_TB6ig8WlxvjQ?pwd=955e

快速入门

RestAPI中其中构建DSL是通过HighLevelRestClient中的resource()来实现的,其中包含了查询、排序、分页、高亮等

RestAPI中其中构建查询条件的核心部分是由一个名为QueryBuilders的工具类提供的,其中包含了各种查询方法

我们通过match_all来演示下基本的API 

SearchRequest request = new SearchRequest("hotel");

相当于

GET /indexName/_search

query(QueryBuilders.matchAllQuery()

相当于

 "query": {
    "match_all": {}
  }

@Test
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);
    //4、解析响应
    handleResponse(response);
}
private void handleResponse(SearchResponse response) {
    //4、解析响应
    SearchHits searchHits = response.getHits();
    //4.1获取总条数
    long total = searchHits.getTotalHits().value;
    System.out.println("共搜索到" + total + "条数据");
    //4.2文档数组
    SearchHit[] hits = searchHits.getHits();
    //4.3遍历
    for (SearchHit hit : hits) {
        //获取文档source
        String json = hit.getSourceAsString();
        //反序列化
        HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
        System.out.println("hotelDoc = " + hotelDoc);
    }
    System.out.println(response);
}
package cn.itcast.hotel;

import cn.itcast.hotel.pojo.HotelDoc;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.Rewriteable;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggester;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.util.CollectionUtils;


import javax.naming.directory.SearchResult;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import static cn.itcast.hotel.constants.HotelConstants.MAPPING_TEMPLATE;

public class HotelSearchTest {
    private RestHighLevelClient client;

    @Test
    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);
        //4、解析响应
        handleResponse(response);
    }

    private void handleResponse(SearchResponse response) {
        //4、解析响应
        SearchHits searchHits = response.getHits();
        //4.1获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到" + total + "条数据");
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        for (SearchHit hit : hits) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            System.out.println("hotelDoc = " + hotelDoc);
        }
        System.out.println(response);
    }

    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.80.130:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        this.client.close();
    }
}

查询到了所有的数据 

全文检索查询

全文检索的match和multi_match查询与match_all的API基本一致。差别是查询条件,也就是query的部分

//单字段查询
QueryBuilders.matchQuery("all","如家");

//多字段查询
QueryBuilders.multiMatchQuery("如家","name","business");

@Test
void testMatch() throws IOException {
    //1、准备Request
    SearchRequest request = new SearchRequest("hotel");
    //2、准备DSL
    request.source().query(QueryBuilders.matchQuery("all","如家"));
    //3、发送请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    //4、解析响应
    handleResponse(response);
}

 private void handleResponse(SearchResponse response) {
        //4、解析响应
        SearchHits searchHits = response.getHits();
        //4.1获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到" + total + "条数据");
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        for (SearchHit hit : hits) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            System.out.println("hotelDoc = " + hotelDoc);
        }
        System.out.println(response);
    }

package cn.itcast.hotel;

import cn.itcast.hotel.pojo.HotelDoc;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.Rewriteable;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggester;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.util.CollectionUtils;


import javax.naming.directory.SearchResult;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import static cn.itcast.hotel.constants.HotelConstants.MAPPING_TEMPLATE;

public class HotelSearchTest {
    private RestHighLevelClient client;

    @Test
    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);
        //4、解析响应
        handleResponse(response);
    }

    @Test
    void testMatch() throws IOException {
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        request.source().query(QueryBuilders.matchQuery("all","如家"));
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        handleResponse(response);
    }

    private void handleResponse(SearchResponse response) {
        //4、解析响应
        SearchHits searchHits = response.getHits();
        //4.1获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到" + total + "条数据");
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        for (SearchHit hit : hits) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            System.out.println("hotelDoc = " + hotelDoc);
        }
        System.out.println(response);
    }

    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.80.130:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        this.client.close();
    }
}

查询到了带有“如家”的数据 

精准查询

精确查询常见的有term查询和range查询,同样利用QueryBuilders实现

//词条查询
QueryBuilders.termQuery ( "city","杭州");

//范围查询
QueryBuilders.rangeQuery( "price").gte( 100).lte( 150); 

复合查询

精确查询常见的有term查询和range查询,同样利用QueryBuilders实现

//创建布尔查询
BoolQueryBuilder boolQuery = QueryBuilders.bgolQuery();

//添加must条件
boolQuery.must(QueryBuilders.termQuery("city","杭州"));

//添加filter条件
boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));

@Test
void testBool() throws IOException {
    //1、准备Request
    SearchRequest request = new SearchRequest("hotel");
    //2、准备DSL
    //2.1、准备booleanQuery
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    //2.2、添加term
    boolQuery.must(QueryBuilders.termQuery("city","上海"));
    //2.3、添加range
    boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));

    request.source().query(boolQuery);
    //3、发送请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    //4、解析响应
    handleResponse(response);
}

   private void handleResponse(SearchResponse response) {
        //4、解析响应
        SearchHits searchHits = response.getHits();
        //4.1获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到" + total + "条数据");
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        for (SearchHit hit : hits) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            System.out.println("hotelDoc = " + hotelDoc);
        }
        System.out.println(response);
    }

package cn.itcast.hotel;

import cn.itcast.hotel.pojo.HotelDoc;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.Rewriteable;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggester;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.util.CollectionUtils;


import javax.naming.directory.SearchResult;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import static cn.itcast.hotel.constants.HotelConstants.MAPPING_TEMPLATE;

public class HotelSearchTest {
    private RestHighLevelClient client;

    @Test
    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);
        //4、解析响应
        handleResponse(response);
    }

    @Test
    void testMatch() throws IOException {
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        request.source().query(QueryBuilders.matchQuery("all","如家"));
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        handleResponse(response);
    }

    @Test
    void testBool() throws IOException {
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        //2.1、准备booleanQuery
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //2.2、添加term
        boolQuery.must(QueryBuilders.termQuery("city","上海"));
        //2.3、添加range
        boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));

        request.source().query(boolQuery);
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        handleResponse(response);
    }

    private void handleResponse(SearchResponse response) {
        //4、解析响应
        SearchHits searchHits = response.getHits();
        //4.1获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到" + total + "条数据");
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        for (SearchHit hit : hits) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            System.out.println("hotelDoc = " + hotelDoc);
        }
        System.out.println(response);
    }


    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.80.130:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        this.client.close();
    }
}

查询出city必须是上海,price必须小于等于250的数据 

排序、分页

搜索结果的排序和分页是与query同级的参数

//查询
request.source().query(QueryBuilders.matchAllQuery());

//分页
request.source( ).from(0).size(5);

//价格排序
request.source().sort("price",SortOrder.ASC);

@Test
void testRageAndSort() throws IOException {
    //页码,每页大小
    int page = 2, size = 5;
    //1、准备Request
    SearchRequest request = new SearchRequest("hotel");
    //2、准备DSL
    //2.1、准备query
    request.source().query(QueryBuilders.matchAllQuery());
    //2.2、排序sort
    request.source().sort("price", SortOrder.ASC);
    //2.3、分页from,size
    request.source().from((page - 1) * size).size(5);
    //3、发送请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    //4、解析响应
    handleResponse(response);
}

    private void handleResponse(SearchResponse response) {
        //4、解析响应
        SearchHits searchHits = response.getHits();
        //4.1获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到" + total + "条数据");
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        for (SearchHit hit : hits) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            System.out.println("hotelDoc = " + hotelDoc);
        }
        System.out.println(response);
    }

package cn.itcast.hotel;

import cn.itcast.hotel.pojo.HotelDoc;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.Rewriteable;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggester;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.util.CollectionUtils;


import javax.naming.directory.SearchResult;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import static cn.itcast.hotel.constants.HotelConstants.MAPPING_TEMPLATE;

public class HotelSearchTest {
    private RestHighLevelClient client;

    @Test
    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);
        //4、解析响应
        handleResponse(response);
    }

    @Test
    void testMatch() throws IOException {
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        request.source().query(QueryBuilders.matchQuery("all","如家"));
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        handleResponse(response);
    }

    @Test
    void testBool() throws IOException {
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        //2.1、准备booleanQuery
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //2.2、添加term
        boolQuery.must(QueryBuilders.termQuery("city","上海"));
        //2.3、添加range
        boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));

        request.source().query(boolQuery);
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        handleResponse(response);
    }

    @Test
    void testRageAndSort() throws IOException {
        //页码,每页大小
        int page = 2, size = 5;
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        //2.1、准备query
        request.source().query(QueryBuilders.matchAllQuery());
        //2.2、排序sort
        request.source().sort("price", SortOrder.ASC);
        //2.3、分页from,size
        request.source().from((page - 1) * size).size(5);
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        handleResponse(response);
    }

   private void handleResponse(SearchResponse response) {
        //4、解析响应
        SearchHits searchHits = response.getHits();
        //4.1获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到" + total + "条数据");
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        for (SearchHit hit : hits) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            System.out.println("hotelDoc = " + hotelDoc);
        }
        System.out.println(response);
    }

    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.80.130:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        this.client.close();
    }
}

查询第二页,每页大小为5 

高亮 

高亮API包括请求DSL构建和结果解析两部分

request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
@Test
void testHighlight() throws IOException {
    //1、准备Request
    SearchRequest request = new SearchRequest("hotel");
    //2、准备DSL
    //2.1、query
    request.source().query(QueryBuilders.matchQuery("all","如家"));
    //2.2、高亮
    request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
    //3、发送请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    //4、解析响应
    handleResponse(response);
}
private void handleResponse(SearchResponse response) {
    //4、解析响应
    SearchHits searchHits = response.getHits();
    //4.1获取总条数
    long total = searchHits.getTotalHits().value;
    System.out.println("共搜索到" + total + "条数据");
    //4.2文档数组
    SearchHit[] hits = searchHits.getHits();
    //4.3遍历
    for (SearchHit hit : hits) {
        //获取文档source
        String json = hit.getSourceAsString();
        //反序列化
        HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
        //获取高亮结果
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        //判断是否有高亮结果
        if(!CollectionUtils.isEmpty(highlightFields)){
            //根据字段名获取高亮结果
            HighlightField highlightField = highlightFields.get("name");
            //判断是否有字段名高亮
            if(highlightField != null){
                //获取高亮值
                String name = highlightField.getFragments()[0].string();
                //覆盖非高亮结果
                hotelDoc.setName(name);
            }
        }
        System.out.println("hotelDoc = " + hotelDoc);
    }
    System.out.println(response);
}
package cn.itcast.hotel;

import cn.itcast.hotel.pojo.HotelDoc;
import com.alibaba.fastjson.JSON;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.Rewriteable;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggester;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.util.CollectionUtils;


import javax.naming.directory.SearchResult;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import static cn.itcast.hotel.constants.HotelConstants.MAPPING_TEMPLATE;

public class HotelSearchTest {
    private RestHighLevelClient client;

    @Test
    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);
        //4、解析响应
        handleResponse(response);
    }

    @Test
    void testMatch() throws IOException {
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        request.source().query(QueryBuilders.matchQuery("all","如家"));
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        handleResponse(response);
    }

    @Test
    void testBool() throws IOException {
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        //2.1、准备booleanQuery
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //2.2、添加term
        boolQuery.must(QueryBuilders.termQuery("city","上海"));
        //2.3、添加range
        boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));

        request.source().query(boolQuery);
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        handleResponse(response);
    }

    @Test
    void testRageAndSort() throws IOException {
        //页码,每页大小
        int page = 2, size = 5;
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        //2.1、准备query
        request.source().query(QueryBuilders.matchAllQuery());
        //2.2、排序sort
        request.source().sort("price", SortOrder.ASC);
        //2.3、分页from,size
        request.source().from((page - 1) * size).size(5);
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        handleResponse(response);
    }

    @Test
    void testHighlight() throws IOException {
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        //2.1、query
        request.source().query(QueryBuilders.matchQuery("all","如家"));
        //2.2、高亮
        request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        handleResponse(response);
    }

    private void handleResponse(SearchResponse response) {
        //4、解析响应
        SearchHits searchHits = response.getHits();
        //4.1获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到" + total + "条数据");
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        for (SearchHit hit : hits) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            //获取高亮结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            //判断是否有高亮结果
            if(!CollectionUtils.isEmpty(highlightFields)){
                //根据字段名获取高亮结果
                HighlightField highlightField = highlightFields.get("name");
                //判断是否有字段名高亮
                if(highlightField != null){
                    //获取高亮值
                    String name = highlightField.getFragments()[0].string();
                    //覆盖非高亮结果
                    hotelDoc.setName(name);
                }
            }
            System.out.println("hotelDoc = " + hotelDoc);
        }
        System.out.println(response);
    }

    @BeforeEach
    void setUp() {
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.80.130:9200")
        ));
    }

    @AfterEach
    void tearDown() throws IOException {
        this.client.close();
    }
}

查询所以内容中有“如家”的数据,并把name加上css的高亮标签 

案例

搜索和查询

在pojo包下创建一个RequestParams.java

package cn.itcast.hotel.pojo;

import lombok.Data;

@Data
public class RequestParams {
    private String key;
    private Integer page;
    private Integer size;
    private String sortBy;
}

在pojo包下创建一个PageResult.java

package cn.itcast.hotel.pojo;

import lombok.Data;

import java.util.List;

@Data
public class PageResult {
    private Long total;
    private List<HotelDoc> hotels;

    public PageResult(Long total, List<HotelDoc> hotels) {
        this.total = total;
        this.hotels = hotels;
    }

    public PageResult() {
    }
}

创建一个web包,下面创建一个HotelController.java

@PostMapping("/list")
public PageResult search(@RequestBody RequestParams params){
    return hotelService.search(params);
}
package cn.itcast.hotel.web;

import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import cn.itcast.hotel.service.IHotelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/hotel")
public class HotelController {

    @Autowired
    private IHotelService hotelService;

    @PostMapping("/list")
    public PageResult search(@RequestBody RequestParams params){
        return hotelService.search(params);
    }

}

IHotelService.java

PageResult search(RequestParams params);
package cn.itcast.hotel.service;

import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import com.baomidou.mybatisplus.extension.service.IService;

import java.util.List;
import java.util.Map;

public interface IHotelService extends IService<Hotel> {
    PageResult search(RequestParams params);
}

HotelService.java

@Override
public PageResult search(RequestParams params) {
    try {
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        //2.1、query
        String key = params.getKey();
        if(key == null || "".equals(key)){
                request.source().query(QueryBuilders.matchAllQuery());
        }else{
                request.source().query(QueryBuilders.matchQuery("all",key));
        }
        //2.2、分页
        int page = params.getPage();
        int size = params.getSize();
        request.source().from((page - 1) * size).size(size);
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        return handleResponse(response);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
private PageResult handleResponse(SearchResponse response) {
    //4、解析响应
    SearchHits searchHits = response.getHits();
    //4.1获取总条数
    long total = searchHits.getTotalHits().value;
    //4.2文档数组
    SearchHit[] hits = searchHits.getHits();
    //4.3遍历
    List<HotelDoc> hotels = new ArrayList<>();
    for (SearchHit hit : hits) {
        //获取文档source
        String json = hit.getSourceAsString();
        //反序列化
        HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
        hotels.add(hotelDoc);
    }
    //4、封装返回
    return new PageResult(total,hotels);
}
package cn.itcast.hotel.service.impl;

import cn.itcast.hotel.mapper.HotelMapper;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.vectorhighlight.ScoreOrderFragmentsBuilder;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {

    @Autowired
    private RestHighLevelClient client;

    @Override
    public PageResult search(RequestParams params) {
    try {
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        //2.1、query
        String key = params.getKey();
        if(key == null || "".equals(key)){
                request.source().query(QueryBuilders.matchAllQuery());
        }else{
                request.source().query(QueryBuilders.matchQuery("all",key));
        }
        //2.2、分页
        int page = params.getPage();
        int size = params.getSize();
        request.source().from((page - 1) * size).size(size);
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        return handleResponse(response);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
 }


    private PageResult handleResponse(SearchResponse response) {
        //4、解析响应
        SearchHits searchHits = response.getHits();
        //4.1获取总条数
        long total = searchHits.getTotalHits().value;
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        List<HotelDoc> hotels = new ArrayList<>();
        for (SearchHit hit : hits) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            hotels.add(hotelDoc);
        }
        //4、封装返回
        return new PageResult(total,hotels);
    }

}

HotelDemoApplication.java

@Bean
public RestHighLevelClient client(){
    return new RestHighLevelClient(RestClient.builder(
            HttpHost.create("http://xxx.xxx.xxx.xxx:9200")
    ));
}
package cn.itcast.hotel;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@MapperScan("cn.itcast.hotel.mapper")
@SpringBootApplication
public class HotelDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(HotelDemoApplication.class, args);
    }

    @Bean
    public RestHighLevelClient client(){
        return new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://xxx.xxx.xxx.xxx:9200")
        ));
    }
}

此时搜索部分完成

结果过滤

RequestParams.java

package cn.itcast.hotel.pojo;

import lombok.Data;

@Data
public class RequestParams {
    private String key;
    private Integer page;
    private Integer size;
    private String sortBy;
    private String city;
    private String brand;
    private String starName;
    private Integer minPrice;
    private Integer maxPrice;
}

HotelService.java

@Override
public PageResult search(RequestParams params) {
    try {
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        //2.1、query
        buildBasicQuery(params,request);
        //2.2、分页
        int page = params.getPage();
        int size = params.getSize();
        request.source().from((page - 1) * size).size(size);
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        return handleResponse(response);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
private void buildBasicQuery(RequestParams params, SearchRequest request) {
    //构建BooleanQuery
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    //关键字搜索
    String key = params.getKey();
    if(key == null || "".equals(key)){
        boolQuery.must(QueryBuilders.matchAllQuery());
    }else{
        boolQuery.must(QueryBuilders.matchQuery("all",key));
    }
    //城市条件
    if(params.getCity() != null && !"".equals(params.getCity())){
        boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
    }
    //品牌条件
    if(params.getBrand() != null && !"".equals(params.getBrand())){
        boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
    }
    //星级条件
    if(params.getStarName() != null && !"".equals(params.getStarName())){
        boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));
    }
    //价格
    if(params.getMinPrice() != null && params.getMaxPrice() != null){     boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
    }
    request.source().query(functionScoreQueryBuilder);
}

private PageResult handleResponse(SearchResponse response) {
    //4、解析响应
    SearchHits searchHits = response.getHits();
    //4.1获取总条数
    long total = searchHits.getTotalHits().value;
    //4.2文档数组
    SearchHit[] hits = searchHits.getHits();
    //4.3遍历
    List<HotelDoc> hotels = new ArrayList<>();
    for (SearchHit hit : hits) {
        //获取文档source
        String json = hit.getSourceAsString();
        //反序列化
        HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
        hotels.add(hotelDoc);
    }
    //4、封装返回
    return new PageResult(total,hotels);
}
package cn.itcast.hotel.service.impl;

import cn.itcast.hotel.mapper.HotelMapper;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.vectorhighlight.ScoreOrderFragmentsBuilder;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {

    @Autowired
    private RestHighLevelClient client;

   @Override
public PageResult search(RequestParams params) {
    try {
        //1、准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2、准备DSL
        //2.1、query
        buildBasicQuery(params,request);
        //2.2、分页
        int page = params.getPage();
        int size = params.getSize();
        request.source().from((page - 1) * size).size(size);
        //3、发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4、解析响应
        return handleResponse(response);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
private void buildBasicQuery(RequestParams params, SearchRequest request) {
    //构建BooleanQuery
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
    //关键字搜索
    String key = params.getKey();
    if(key == null || "".equals(key)){
        boolQuery.must(QueryBuilders.matchAllQuery());
    }else{
        boolQuery.must(QueryBuilders.matchQuery("all",key));
    }
    //城市条件
    if(params.getCity() != null && !"".equals(params.getCity())){
        boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
    }
    //品牌条件
    if(params.getBrand() != null && !"".equals(params.getBrand())){
        boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
    }
    //星级条件
    if(params.getStarName() != null && !"".equals(params.getStarName())){
        boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));
    }
    //价格
    if(params.getMinPrice() != null && params.getMaxPrice() != null){     boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
    }
    request.source().query(functionScoreQueryBuilder);
}

private PageResult handleResponse(SearchResponse response) {
    //4、解析响应
    SearchHits searchHits = response.getHits();
    //4.1获取总条数
    long total = searchHits.getTotalHits().value;
    //4.2文档数组
    SearchHit[] hits = searchHits.getHits();
    //4.3遍历
    List<HotelDoc> hotels = new ArrayList<>();
    for (SearchHit hit : hits) {
        //获取文档source
        String json = hit.getSourceAsString();
        //反序列化
        HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
        hotels.add(hotelDoc);
    }
    //4、封装返回
    return new PageResult(total,hotels);
}

}

此时结果可以过滤了

周边

RequestParams.java

package cn.itcast.hotel.pojo;

import lombok.Data;

@Data
public class RequestParams {
    private String key;
    private Integer page;
    private Integer size;
    private String sortBy;
    private String city;
    private String brand;
    private String starName;
    private Integer minPrice;
    private Integer maxPrice;
    private String location;
}

HotelDoc.java

package cn.itcast.hotel.pojo;

import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.*;

@Data
@NoArgsConstructor
public class HotelDoc {
    private Long id;
    private String name;
    private String address;
    private Integer price;
    private Integer score;
    private String brand;
    private String city;
    private String starName;
    private String business;
    private String location;
    private String pic;
    private Object distance;
   public HotelDoc(Hotel hotel) {
        this.id = hotel.getId();
        this.name = hotel.getName();
        this.address = hotel.getAddress();
        this.price = hotel.getPrice();
        this.score = hotel.getScore();
        this.brand = hotel.getBrand();
        this.city = hotel.getCity();
        this.starName = hotel.getStarName();
        this.business = hotel.getBusiness();
        this.location = hotel.getLatitude() + ", " + hotel.getLongitude();
        this.pic = hotel.getPic();
      
    }
}

HotelService.java

 @Override
    public PageResult search(RequestParams params) {
        try {
            //1、准备Request
            SearchRequest request = new SearchRequest("hotel");
            //2、准备DSL
            //2.1、query
            buildBasicQuery(params,request);
            //2.2、分页
            int page = params.getPage();
            int size = params.getSize();
            request.source().from((page - 1) * size).size(size);
            //2.3、排序
            String location = params.getLocation();
            if(location != null && !"".equals(location)){
                request.source().sort(SortBuilders
                        .geoDistanceSort("location",new GeoPoint(location))
                        .order(SortOrder.ASC)
                        .unit(DistanceUnit.KILOMETERS)
                );
            }
            //3、发送请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            //4、解析响应
            return handleResponse(response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void buildBasicQuery(RequestParams params, SearchRequest request) {
        //构建BooleanQuery
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //关键字搜索
        String key = params.getKey();
        if(key == null || "".equals(key)){
            boolQuery.must(QueryBuilders.matchAllQuery());
        }else{
            boolQuery.must(QueryBuilders.matchQuery("all",key));
        }
        //城市条件
        if(params.getCity() != null && !"".equals(params.getCity())){
            boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
        }
        //品牌条件
        if(params.getBrand() != null && !"".equals(params.getBrand())){
            boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
        }
        //星级条件
        if(params.getStarName() != null && !"".equals(params.getStarName())){
            boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));
        }
        //价格
        if(params.getMinPrice() != null && params.getMaxPrice() != null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
        }

        request.source().query(functionScoreQueryBuilder);
    }

    private PageResult handleResponse(SearchResponse response) {
        //4、解析响应
        SearchHits searchHits = response.getHits();
        //4.1获取总条数
        long total = searchHits.getTotalHits().value;
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        List<HotelDoc> hotels = new ArrayList<>();
        for (SearchHit hit : hits) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            //获取距离
            Object[] sortValues = hit.getSortValues();
            if(sortValues.length > 0){
                Object sortValue = sortValues[0];
                hotelDoc.setDistance(sortValue);
            }
            hotels.add(hotelDoc);
        }
        //4、封装返回
        return new PageResult(total,hotels);
    }
 

package cn.itcast.hotel.service.impl;

import cn.itcast.hotel.mapper.HotelMapper;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.vectorhighlight.ScoreOrderFragmentsBuilder;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {

    @Autowired
    private RestHighLevelClient client;

    @Override
    public PageResult search(RequestParams params) {
        try {
            //1、准备Request
            SearchRequest request = new SearchRequest("hotel");
            //2、准备DSL
            //2.1、query
            buildBasicQuery(params,request);
            //2.2、分页
            int page = params.getPage();
            int size = params.getSize();
            request.source().from((page - 1) * size).size(size);
            //2.3、排序
            String location = params.getLocation();
            if(location != null && !"".equals(location)){
                request.source().sort(SortBuilders
                        .geoDistanceSort("location",new GeoPoint(location))
                        .order(SortOrder.ASC)
                        .unit(DistanceUnit.KILOMETERS)
                );
            }
            //3、发送请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            //4、解析响应
            return handleResponse(response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void buildBasicQuery(RequestParams params, SearchRequest request) {
        //构建BooleanQuery
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //关键字搜索
        String key = params.getKey();
        if(key == null || "".equals(key)){
            boolQuery.must(QueryBuilders.matchAllQuery());
        }else{
            boolQuery.must(QueryBuilders.matchQuery("all",key));
        }
        //城市条件
        if(params.getCity() != null && !"".equals(params.getCity())){
            boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
        }
        //品牌条件
        if(params.getBrand() != null && !"".equals(params.getBrand())){
            boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
        }
        //星级条件
        if(params.getStarName() != null && !"".equals(params.getStarName())){
            boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));
        }
        //价格
        if(params.getMinPrice() != null && params.getMaxPrice() != null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
        }

        request.source().query(functionScoreQueryBuilder);
    }

    private PageResult handleResponse(SearchResponse response) {
        //4、解析响应
        SearchHits searchHits = response.getHits();
        //4.1获取总条数
        long total = searchHits.getTotalHits().value;
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        List<HotelDoc> hotels = new ArrayList<>();
        for (SearchHit hit : hits) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            //获取距离
            Object[] sortValues = hit.getSortValues();
            if(sortValues.length > 0){
                Object sortValue = sortValues[0];
                hotelDoc.setDistance(sortValue);
            }
            hotels.add(hotelDoc);
        }
        //4、封装返回
        return new PageResult(total,hotels);
    }

}

此时可以看到距离

竞价排名

RequestParams.java

package cn.itcast.hotel.pojo;

import lombok.Data;

@Data
public class RequestParams {
    private String key;
    private Integer page;
    private Integer size;
    private String sortBy;
    private String city;
    private String brand;
    private String starName;
    private Integer minPrice;
    private Integer maxPrice;
    private String location;
}

HotelDoc.java

package cn.itcast.hotel.pojo;

import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.*;

@Data
@NoArgsConstructor
public class HotelDoc {
    private Long id;
    private String name;
    private String address;
    private Integer price;
    private Integer score;
    private String brand;
    private String city;
    private String starName;
    private String business;
    private String location;
    private String pic;
    private Object distance;
    private Boolean isAD;
    private List<String> suggestion;

    public HotelDoc(Hotel hotel) {
        this.id = hotel.getId();
        this.name = hotel.getName();
        this.address = hotel.getAddress();
        this.price = hotel.getPrice();
        this.score = hotel.getScore();
        this.brand = hotel.getBrand();
        this.city = hotel.getCity();
        this.starName = hotel.getStarName();
        this.business = hotel.getBusiness();
        this.location = hotel.getLatitude() + ", " + hotel.getLongitude();
        this.pic = hotel.getPic();
      
    }
}

HotelService.java

package cn.itcast.hotel.service.impl;

import cn.itcast.hotel.mapper.HotelMapper;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.pojo.PageResult;
import cn.itcast.hotel.pojo.RequestParams;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.lucene.queries.function.FunctionScoreQuery;
import org.apache.lucene.search.vectorhighlight.ScoreOrderFragmentsBuilder;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {

    @Autowired
    private RestHighLevelClient client;

    @Override
    public PageResult search(RequestParams params) {
        try {
            //1、准备Request
            SearchRequest request = new SearchRequest("hotel");
            //2、准备DSL
            //2.1、query
            buildBasicQuery(params,request);
            //2.2、分页
            int page = params.getPage();
            int size = params.getSize();
            request.source().from((page - 1) * size).size(size);
            //2.3、排序
            String location = params.getLocation();
            if(location != null && !"".equals(location)){
                request.source().sort(SortBuilders
                        .geoDistanceSort("location",new GeoPoint(location))
                        .order(SortOrder.ASC)
                        .unit(DistanceUnit.KILOMETERS)
                );
            }
            //3、发送请求
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            //4、解析响应
            return handleResponse(response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    private void buildBasicQuery(RequestParams params, SearchRequest request) {
        //构建BooleanQuery
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //关键字搜索
        String key = params.getKey();
        if(key == null || "".equals(key)){
            boolQuery.must(QueryBuilders.matchAllQuery());
        }else{
            boolQuery.must(QueryBuilders.matchQuery("all",key));
        }
        //城市条件
        if(params.getCity() != null && !"".equals(params.getCity())){
            boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
        }
        //品牌条件
        if(params.getBrand() != null && !"".equals(params.getBrand())){
            boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
        }
        //星级条件
        if(params.getStarName() != null && !"".equals(params.getStarName())){
            boolQuery.filter(QueryBuilders.termQuery("starName", params.getStarName()));
        }
        //价格
        if(params.getMinPrice() != null && params.getMaxPrice() != null){
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(params.getMinPrice()).lte(params.getMaxPrice()));
        }
  

        request.source().query(functionScoreQueryBuilder);
    }

    private PageResult handleResponse(SearchResponse response) {
        //4、解析响应
        SearchHits searchHits = response.getHits();
        //4.1获取总条数
        long total = searchHits.getTotalHits().value;
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        List<HotelDoc> hotels = new ArrayList<>();
        for (SearchHit hit : hits) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            //获取距离
            Object[] sortValues = hit.getSortValues();
            if(sortValues.length > 0){
                Object sortValue = sortValues[0];
                hotelDoc.setDistance(sortValue);
            }
            hotels.add(hotelDoc);
        }
        //4、封装返回
        return new PageResult(total,hotels);
    }

}

此时优先显示近的周边

代码文件点击下载https://pan.baidu.com/s/1e_aKaZ8Qvo1GG3nbFe97zQ?pwd=81s2 上一篇:ES的安装和RestClient的操作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1349252.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

将学习自动化测试时的医药管理信息系统项目用idea运行

将学习自动化测试时的医药管理信息系统项目用idea运行 背景 学习自动化测试的时候老师的运行方式是把医药管理信息系统项目打包成war包后再放到tomcat的webapp中去运行&#xff0c;于是我想着用idea运行会方便点&#xff0c;现在记录下步骤方便以后查找最开始没有查阅资料&am…

【心得】PHP反序列化高级利用(phar|session)个人笔记

目录 ①phar反序列化 ②session反序列化 ①phar反序列化 phar 认为是java的jar包 calc.exe phar能干什么 多个php合并为独立压缩包&#xff0c;不解压就能执行里面的php文件&#xff0c;支持web服务器和命令行 phar协议 phar://xxx.phar $phar->setmetadata($h); m…

LanceDB:在对抗数据复杂性战役中,您可信赖的坐骑

LanceDB 建立在 Lance&#xff08;一种开源列式数据格式&#xff09;之上&#xff0c;具有一些有趣的功能&#xff0c;使其对 AI/ML 具有吸引力。例如&#xff0c;LanceDB 支持显式和隐式矢量化&#xff0c;能够处理各种数据类型。LanceDB 与 PyTorch 和 TensorFlow 等领先的 M…

三菱人机交互GT Designer的使用(三,指示灯,数值显示与输入,字符串显示与输入,日期|时间的显示)

今天继续对GT进行学习&#xff0c;如有不妥&#xff0c;欢迎指正&#xff01;&#xff01;&#xff01; 目录 指示灯设置 设置指示灯 位指示灯 字指示灯 数值输入&#xff0c;输出&#xff08;二者差距不大&#xff09; 数值显示与输出 数值显示&#xff08;只能显示&…

【Maven】工程依赖下载失败错误解决

在使用 Maven 构建项目时&#xff0c;可能会发生依赖项下载错误的情况&#xff0c;主要原因有以下几种&#xff1a; 下载依赖时出现网络故障或仓库服务器宕机等原因&#xff0c;导致无法连接至 Maven 仓库&#xff0c;从而无法下载依赖。 依赖项的版本号或配置文件中的版本号错…

【计算机毕业设计】ssm+mysql+jsp实现的在线bbs论坛系统源码

项目介绍 jspssm&#xff08;springspringMVCmybatis&#xff09;MySQL实现的在线bbs论坛系统源码&#xff0c;本系统主要实现了前台用户注册登陆、浏览帖子、发布帖子、个人信息管理、消息通知管理&#xff0c;积分管理&#xff0c;后台管理功能有&#xff1a;友情链接管理、…

怎么设计一个简单又直观的接口?

文章目录 问题的开端为什么从问题开始&#xff1f;自然而来的接口 一个接口一件事情减少依赖关系使用方式要“傻” 小结 开放的接口规范是使用者和实现者之间的合约。既然是合约&#xff0c;就要成文、清楚、稳定。合约是好东西&#xff0c;它可以让代码之间的组合有规可依。但…

Stable Diffusion API入门:简明教程

Stable Diffusion 是一个先进的深度学习模型&#xff0c;用于创造和修改图像。这个模型能够基于文本描述来生成图像&#xff0c;让机器理解和实现用户的创意。使用这项技术的关键在于掌握其 API&#xff0c;通过编程来操控图像生成的过程。 在探索 Stable Diffusion API 的世界…

爱思唯尔的KBS——模板、投稿、返修、接收的总结

第二篇论文终于是接受了QAQ&#xff0c;被审稿人疯狂拖时间&#xff0c;KBS是真难绷啊 由于之前发布过关于爱思唯尔旗下的ESWA博客&#xff0c;KBS和ESWA是类似的&#xff0c;因此本篇博客主要说下区别以及期间碰到的各种情况&#xff0c;有疑问依然可以在评论区说&#xff0c;…

【C语言】函数

函数是什么&#xff1f; “函数”是我们早些年在学习数学的过程中常见的概念&#xff0c;简单回顾一下&#xff1a;比如下图中&#xff0c;你给函数 f(x)2*x3 一个具体的x,这个函数通过一系列的计算来返回给你一个结果(图示如下)。 这就是数学中函数的基本过程和作用。但是你…

48、激活函数 - 梯度消失和梯度爆炸

简单介绍下梯度消失和梯度爆炸,这个不是重点,但是我觉得有必要再深入了解这个概念,以及很多激活函数为什么是可以防止梯度消失的。 梯度消失和梯度爆炸实际上是在神经网络训练过程中经常会遇到的两类问题,这两类问题都与梯度有关。 什么是梯度 在神经网络训练中,梯度是指…

Final Cut 视频剪辑快速入门,小白上手视频课的制作

本文是一个快速入门教程&#xff0c;如果您是0视频处理基础&#xff0c;又想录制网课或是一些对效果要求不高的视频那么这篇教程足够使用了。 本文主要用Final Cut处理视频课&#xff0c;本文是笔者在制作视频课过程中逐渐摸索的&#xff0c;如果您想制作一些比较专业的视频&a…

mysql原理--Explain详解

1.概述 一条查询语句在经过 MySQL 查询优化器的各种基于成本和规则的优化会后生成一个所谓的 执行计划 &#xff0c;这个执行计划展示了接下来具体执行查询的方式&#xff0c;比如多表连接的顺序是什么&#xff0c;对于每个表采用什么访问方法来具体执行查询等等。设计 MySQL 的…

【LMM 003】生物医学领域的垂直类大型多模态模型 LLaVA-Med

论文标题&#xff1a;LLaVA-Med: Training a Large Language-and-Vision Assistant for Biomedicine in One Day 论文作者&#xff1a;Chunyuan Li∗, Cliff Wong∗, Sheng Zhang∗, Naoto Usuyama, Haotian Liu, Jianwei Yang Tristan Naumann, Hoifung Poon, Jianfeng Gao 作…

uni-app 前后端调用实例 基于Springboot 下拉刷新实现

锋哥原创的uni-app视频教程&#xff1a; 2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中...共计23条视频&#xff0c;包括&#xff1a;第1讲 uni…

UDS诊断(ISO14229-1) 11服务

文章目录 功能简介应用场景请求和响应1、请求2、子功能3、肯定响应4、否定响应 报文示例UDS中常用 NRC参考 功能简介 11服务&#xff0c;即 ECUReset&#xff08;ECU重置&#xff09;服务&#xff0c;用来控制MCU进行重启&#xff0c;重启分为硬件重启和软件重启。 应用场景…

事件循环的理解

1.单线程 Js是一个单线程的语言,代码只能一行一行去执行,遇到同步的代码就直接执行了,如果遇到异步的代码怎么办&#xff1f; 不可能等到异步的代码执行完&#xff0c;在去执行后面同步的代码。 2.主线程 遇到同步的代码,就在主线程里面直接执行了。 3.任务队列 遇到异步的…

Vue中使用JavaScript中的requestAnimationFrame动画循环实现循环滚动效果-demo

效果 requestAnimationFrame是一个由浏览器提供的 JavaScript 方法&#xff0c;用于在下一次浏览器重绘之前执行指定的回调函数。它接受一个回调函数作为参数&#xff0c;并返回一个整数值&#xff0c;可以用于取消动画循环。 使用 requestAnimationFrame 可以创建平滑的动画效…

【AIGC-图片生成视频系列-5】I2V-Adapter:一种用于视频扩散模型的通用图像生成视频适配器

目录 一. 项目与贡献概述 二. 方法详解 a. 整体框架图 b. 帧相似性先验 三. 一般化图像生成动画结果 四. 基于个性化 T2I 模型的动画结果 五. 结合ControlNet动画结果 六. 项目论文和代码 七. 个人思考与总结 在快速发展的数字内容生成领域&#xff0c;焦点已从文本到…

C#中的Attribute详解(下)

C#中的Attribute详解&#xff08;下&#xff09; 一、Attribute本质二、Attribute实例化三、Attribute实例化的独特之处四、元数据的作用五、自定义Attribute实例六、Attribute的附着目标七、附加问题 一、Attribute本质 从上篇里我们可以看到&#xff0c;Attribute似乎总跟pu…