赞
踩
目录
内容基于黑马程序员学习记录,既然Elastic是基于Restful来进行操作的,那么肯定各种语言都有操作他的方式,这里我分享一下javaRestClient如何操作es索引库。
- <dependency>
- <groupId>org.elasticsearch.client</groupId>
- <artifactId>elasticsearch-rest-high-level-client</artifactId>
- </dependency>
- <properties>
- <java.version>1.8</java.version>
- <!--因为springboot父工程默认es为7.6定义了版本所以需要根据自己的es版本在properties修改-->
- <elasticsearch.version>7.12.1</elasticsearch.version>
- </properties>
在使用前要初始化连接,使用后要关闭连接
- private RestHighLevelClient client;
-
- /**
- * 建立es连接
- */
- @BeforeEach
- void setClient() {
- this.client = new RestHighLevelClient(RestClient.builder(
- HttpHost.create("http://ip:9200")
- ));
- }
-
- /**
- * 关闭连接
- * @throws IOException
- */
- @AfterEach
- void tearDown() throws IOException {
- this.client.close();
- }

MAPPING_TEMPLATE为已经封装好的DSL建表语句,代码过长就进行了单独封装
- public class HotelConstants {
- public static final String MAPPING_TEMPLATE = "{\n" +
- " \"mappings\": {\n" +
- " \"properties\": {\n" +
- " \"id\":{\n" +
- " \"type\": \"keyword\"\n" +
- " },\n" +
- " \"name\":{\n" +
- " \"type\": \"text\",\n" +
- " \"analyzer\": \"ik_max_word\",\n" +
- " \"copy_to\": \"all\"\n" +
- " },\n" +
- " \"address\":{\n" +
- " \"type\": \"text\",\n" +
- " \"index\": false\n" +
- " },\n" +
- " \"price\":{\n" +
- " \"type\": \"integer\"\n" +
- " },\n" +
- " \"score\":{\n" +
- " \"type\": \"integer\"\n" +
- " },\n" +
- " \"brand\":{\n" +
- " \"type\": \"keyword\",\n" +
- " \"copy_to\": \"all\"\n" +
- " },\n" +
- " \"city\":{\n" +
- " \"type\": \"keyword\"\n" +
- " },\n" +
- " \"starName\":{\n" +
- " \"type\": \"keyword\"\n" +
- " },\n" +
- " \"business\":{\n" +
- " \"type\": \"keyword\",\n" +
- " \"copy_to\": \"all\"\n" +
- " },\n" +
- " \"location\":{\n" +
- " \"type\": \"geo_point\"\n" +
- " },\n" +
- " \"pic\":{\n" +
- " \"type\": \"keyword\",\n" +
- " \"index\": false\n" +
- " },\n" +
- " \"all\":{\n" +
- " \"type\": \"text\",\n" +
- " \"analyzer\": \"ik_max_word\"\n" +
- " }\n" +
- " }\n" +
- " }\n" +
- "}";
- }

- /**
- * 创建es索引库代码
- * @throws IOException
- */
- @Test
- void creatHotelIndex() throws IOException {
- //创建Request对象
- CreateIndexRequest request = new CreateIndexRequest("hotel");
- //准备请求的参数,DSL语句
- request.source(MAPPING_TEMPLATE, XContentType.JSON);
- //发送请求
- client.indices().create(request, RequestOptions.DEFAULT);
- }
新增文档,这里是将数据库里的数据增添到es中,先调用service的接口查询数据,因为数据库中对于坐标的存放方式为横坐标、纵坐标,而es里是横纵坐标用,间隔拼接的字符串,所以用HotelDoc进行单独处理。
- @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;
-
- 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();
- }
- }

- /**
- * 新增es文档
- * @throws IOException
- */
- @Test
- void testAddDocument() throws IOException {
- //根据id查询酒店
- Hotel hotel = hotelService.getById(61083L);
- //转换为文档信息
- HotelDoc hotelDoc = new HotelDoc(hotel);
- //准备request对象
- IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
- //将hotel转换为json格式
- request.source(JSON.toJSONString(hotel),XContentType.JSON);
- //发送请求
- client.index(request,RequestOptions.DEFAULT);
- }

- /**
- * 根据id删除文档
- * @throws IOException
- */
- @Test
- void testDelDocument() throws IOException {
- DeleteRequest request = new DeleteRequest("hotel","61083");
- client.delete(request,RequestOptions.DEFAULT);
- }
- /**
- * 根据id查询es文档
- * @throws IOException
- */
- @Test
- void testGetDocumentById() throws IOException {
- GetRequest request = new GetRequest("hotel","61083");
- //发送请求,得到响应
- GetResponse response = client.get(request,RequestOptions.DEFAULT);
- String json = response.getSourceAsString();
- HotelDoc hotelDoc = JSON.parseObject(json,HotelDoc.class);
- System.out.println(hotelDoc);
- }
- /**
- * 更新es文档
- * @throws IOException
- */
- @Test
- void testUpdateDocument() throws IOException {
- UpdateRequest request = new UpdateRequest("hotel","61083");
- //准备修改的字段请求参数
- request.doc(
- "price" , "999",
- "starName" , "4星"
- );
- client.update(request,RequestOptions.DEFAULT);
- }
实际是将很多新增文档语句整合在一起:
- /**
- * 批量添加文档
- */
- @Test
- void testBulkRequest() throws IOException {
- List<Hotel> hotels = hotelService.list();
- //准备request对象,BulkRequest实际是将多个index请求整合起来
- BulkRequest request = new BulkRequest();
- for (Hotel hotel : hotels) {
- HotelDoc hotelDoc = new HotelDoc(hotel);
- request.add(new IndexRequest("hotel")
- .id(hotelDoc.getId().toString())
- .source(JSON.toJSONString(hotelDoc),XContentType.JSON));
- }
- //发送请求
- client.bulk(request,RequestOptions.DEFAULT);
- }

对于查询结果的操作,因为es的高亮查询后高亮的字段是进行单独封装的,在highlight对象里,所以进行高亮显示的查询才进行相应的结果处理,不然会报数组为空:
- private void handleResponse(SearchResponse response) {
- 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) {
- // 4.4.获取source
- String json = hit.getSourceAsString();
- // 4.5.反序列化,非高亮的
- HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
- // // 4.6.处理高亮结果
- // // 1)获取高亮map
- // Map<String, HighlightField> map = hit.getHighlightFields();
- // // 2)根据字段名,获取高亮结果
- // HighlightField highlightField = map.get("name");
- // // 3)获取高亮结果字符串数组中的第1个元素
- // String hName = highlightField.getFragments()[0].toString();
- // // 4)把高亮结果放到HotelDoc中
- // hotelDoc.setName(hName);
- // 4.7.打印
- System.out.println(hotelDoc);
- }
- }

- @Test
- void testMatch() throws IOException {
- // 1.准备request
- SearchRequest request = new SearchRequest("hotel");
- // 2.准备请求参数
- //查所有 request.source().query(QueryBuilders.matchAllQuery());
- //全文检索查一个字段满足的数据 request.source().query(QueryBuilders.matchQuery("all", "外滩如家"));
- //全文检索查多个字段满足 request.source().query(QueryBuilders.multiMatchQuery("外滩如家", "name", "brand", "city"));
- //精确查询位置为北京 request.source().query(QueryBuilders.termQuery("city","北京"));
- //精确查询价格<=250的酒店,lt: <,gt: >,gte: >=
- // request.source().query(QueryBuilders.rangeQuery("price").lte(250));
- //精确查询地图矩形范围内酒店,分别为上经度左纬度下经度右纬度
- //request.source().query(QueryBuilders.geoBoundingBoxQuery("location").setCorners(top, left, bottom, right));
- // 3.发送请求,得到响应
- SearchResponse response = client.search(request, RequestOptions.DEFAULT);
- // 4.结果解析
- handleResponse(response);
- }

为了节省时间和内存,对于多字段的全文检索查询一般都是在建索引库时将多个需要全文检索的字段copy到一起,比如这里的all。
- void testHighlight() throws IOException {
- // 1.准备request
- SearchRequest request = new SearchRequest("hotel");
- // 2.准备请求参数
- // 2.1.query
- request.source().query(QueryBuilders.matchQuery("all", "外滩如家"));
- // 2.2.高亮,es默认情况下高亮字段必须与搜索字段匹配,但是也可以通过requireFieldMatch(false)关闭
- request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
- // 3.发送请求,得到响应
- SearchResponse response = client.search(request, RequestOptions.DEFAULT);
- // 4.结果解析
- handleResponse(response);
- }
- void testBool() throws IOException {
- // 1.准备request
- SearchRequest request = new SearchRequest("hotel");
- // 2.准备请求参数
- /*
- BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
- // 2.1.must
- boolQuery.must(QueryBuilders.termQuery("city", "杭州"));
- // 2.2.filter
- boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));
- */
-
- request.source().query(
- QueryBuilders.boolQuery()
- .must(QueryBuilders.termQuery("city", "杭州"))
- .filter(QueryBuilders.rangeQuery("price").lte(250))
- );
- // 3.发送请求,得到响应
- SearchResponse response = client.search(request, RequestOptions.DEFAULT);
- // 4.结果解析
- handleResponse(response);
- }

- void testSortAndPage() throws IOException {
- //前端传页数和每页数量
- int page = 1,size = 5;
-
- // 1.准备request
- SearchRequest request = new SearchRequest("hotel");
- // 2.准备请求参数
- // 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(size);
-
- // 3.发送请求,得到响应
- SearchResponse response = client.search(request, RequestOptions.DEFAULT);
- // 4.结果解析
- handleResponse(response);
- }

- void testNeighborhood() throws IOException {
- // 1.准备request
- SearchRequest request = new SearchRequest("hotel");
- // 2.准备请求参数
- // 查询十公里内酒店
- request.source().query(
- QueryBuilders.geoDistanceQuery("location")
- .distance("10km")
- .point(new GeoPoint(39.914539, 116.413392)));
- // 构建GeoDistanceSortBuilder设置按距离排序参数
- GeoDistanceSortBuilder geoDistanceSortBuilder = SortBuilders.geoDistanceSort("location", new GeoPoint(39.914539, 116.413392));
- // 升序排序
- geoDistanceSortBuilder.order(SortOrder.ASC);
- request.source().sort(geoDistanceSortBuilder);
- // 3.发送请求,得到响应
- SearchResponse response = client.search(request, RequestOptions.DEFAULT);
- // 4.结果解析
- handleResponse(response);
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。