一、前言
ES 提供多种不同的客户端:
不推荐使用:
1、TransportClient
ES 提供的传统客户端,官方计划 8.0 版本删除此客户端。
2、RestClient
Elasticsearch 提供了两个 JAVA REST Client 版本:
java low level rest client
低级别的 rest 客户端,通过 http 与集群交互,用户需自己编组请求 JSON 串,及解析响应 JSON 串。兼容所有 Elasticsearch 版本。
java high rest client
高级别的 REST 客户端,基于低级别的 REST 客户端,增加了编组请求 JSON 串、解析响应 JSON 串等相关 API,使用的版本需要保存和 ES 服务一致的版本,否则会有版本问题。
兼容性说明:
依赖 jdk1.8 和 Elasticsearch core project
这里使用高级客户端:java high rest client。
二、准备工作
创建一个 SpringBoot 项目 elasticsearch-demo
导入 pom 坐标
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.4.1</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>7.4.1</version> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>7.4.1</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.4</version> </dependency>
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
|
resource
文件夹下修改 application.yml
文件
1 2 3
| elasticsearch: host: 192.168.88.88 port: 9200
|
创建 ElasticSearchConfig
配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| @Configuration @ConfigurationProperties(prefix = "elasticsearch") public class ElasticSearchConfig { private String host; private int port;
public String getHost() { return host; }
public void setHost(String host) { this.host = host; }
public int getPort() { return port; }
public void setPort(int port) { this.port = port; }
@Bean public RestHighLevelClient client() { return new RestHighLevelClient(RestClient.builder( new HttpHost( host, port, "http" ) )); } }
|
新建测试类ElasticsearchTest
,测试是否能正常连接
1 2 3 4 5 6 7 8 9 10
| @RunWith(SpringRunner.class) @SpringBootTest public class ElasticsearchTest { @Autowired private RestHighLevelClient client;
@Test public void contextLoads() { System.out.println(client); }
|
三、具体操作
1、创建索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
@Test public void addIndex() throws Exception { IndicesClient indicesClient = client.indices(); CreateIndexRequest createRequest = new CreateIndexRequest("abc"); CreateIndexResponse response = indicesClient.create(createRequest, RequestOptions.DEFAULT);
System.out.println(response.isAcknowledged()); }
|
2、添加索引和映射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
@Test public void addIndexAndMapping() throws IOException { IndicesClient indicesClient = client.indices(); CreateIndexRequest createRequest = new CreateIndexRequest("aaa"); String mapping = "{\n" + " \"properties\" : {\n" + " \"address\" : {\n" + " \"type\" : \"text\",\n" + " \"analyzer\" : \"ik_max_word\"\n" + " },\n" + " \"age\" : {\n" + " \"type\" : \"long\"\n" + " },\n" + " \"name\" : {\n" + " \"type\" : \"keyword\"\n" + " }\n" + " }\n" + " }"; createRequest.mapping(mapping, XContentType.JSON);
CreateIndexResponse response = indicesClient.create(createRequest, RequestOptions.DEFAULT);
System.out.println(response.isAcknowledged()); }
|
3、查询索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
@Test public void queryIndex() throws IOException { IndicesClient indices = client.indices();
GetIndexRequest getReqeust = new GetIndexRequest("aaa"); GetIndexResponse response = indices.get(getReqeust, RequestOptions.DEFAULT);
Map<String, MappingMetaData> mappings = response.getMappings(); for (String key : mappings.keySet()) { System.out.println(key + ":" + mappings.get(key).getSourceAsMap()); } }
|
4、删除索引
1 2 3 4 5 6 7 8 9 10 11 12
|
@Test public void deleteIndex() throws IOException { IndicesClient indices = client.indices();
DeleteIndexRequest deleteRequest = new DeleteIndexRequest("abc"); AcknowledgedResponse response = indices.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(response.isAcknowledged()); }
|
5、判断索引是否存在
1 2 3 4 5 6 7 8 9 10 11 12
|
@Test public void existIndex() throws IOException { IndicesClient indices = client.indices();
GetIndexRequest getRequest = new GetIndexRequest("aaa"); boolean exists = indices.exists(getRequest, RequestOptions.DEFAULT);
System.out.println(exists); }
|
6、添加文档,使用 map 作为数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
@Test public void addDoc() throws IOException { Map data = new HashMap(); data.put("address", "深圳"); data.put("name", "南山"); data.put("age", 20);
IndexRequest request = new IndexRequest("aaa").id("1").source(data); IndexResponse response = client.index(request, RequestOptions.DEFAULT);
System.out.println(response.getId()); }
|
7、添加文档,使用对象作为数据
创建 Person 实体类
1 2 3 4 5 6 7 8
| public class Person { private String id; private String name; private int age; private String address;
}
|
使用对象作为数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
@Test public void addDoc2() throws IOException { Person p = new Person(); p.setId("2"); p.setName("上海"); p.setAge(30); p.setAddress("宝山区");
String data = JSON.toJSONString(p);
IndexRequest request = new IndexRequest("aaa").id(p.getId()).source(data, XContentType.JSON); IndexResponse response = client.index(request, RequestOptions.DEFAULT); System.out.println(response.getId()); }
|
8、修改文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
@Test public void updateDoc() throws IOException { Person p = new Person(); p.setId("2"); p.setName("北京"); p.setAge(30); p.setAddress("北京昌平区");
String data = JSON.toJSONString(p);
IndexRequest request = new IndexRequest("aaa").id(p.getId()).source(data, XContentType.JSON); IndexResponse response = client.index(request, RequestOptions.DEFAULT);
System.out.println(response.getId()); }
|
9、根据 id 查询文档
1 2 3 4 5 6 7 8 9 10 11 12
|
@Test public void findDocById() throws IOException {
GetRequest getReqeust = new GetRequest("aaa", "1"); GetResponse response = client.get(getReqeust, RequestOptions.DEFAULT); System.out.println(response.getSourceAsString()); }
|
10、根据 id 删除文档
1 2 3 4 5 6 7 8 9
|
@Test public void delDoc() throws IOException { DeleteRequest deleteRequest = new DeleteRequest("aaa", "1"); DeleteResponse response = client.delete(deleteRequest, RequestOptions.DEFAULT); System.out.println(response.getId()); }
|
11、批量操作-脚本
Bulk 批量操作是将文档的增删改查一些列操作,通过一次请求全都做完。减少网络传输次数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
@Test public void testBulk() throws IOException { BulkRequest bulkRequest = new BulkRequest();
DeleteRequest deleteRequest = new DeleteRequest("person", "1"); bulkRequest.add(deleteRequest);
Map map = new HashMap(); map.put("name", "六号"); IndexRequest indexRequest = new IndexRequest("person").id("6").source(map); bulkRequest.add(indexRequest);
Map map2 = new HashMap(); map2.put("name", "三号"); UpdateRequest updateReqeust = new UpdateRequest("person", "3").doc(map2); bulkRequest.add(updateReqeust);
BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT); RestStatus status = response.status(); System.out.println(status); }
|
12、导入数据
将数据库中 Goods 表的数据导入到 ElasticSearch 中
添加坐标
1 2 3 4 5 6 7 8 9 10
| <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
|
application.yml
配置文件添加 mybatis 相关配置
1 2 3 4 5 6 7 8 9 10 11 12
| spring: datasource: url: jdbc:mysql://192.168.88.88:3306/es?serverTimezone=UTC username: root password: root
mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.atguigu.domain
|
添加 javabean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package com.atguigu.config.domain;
import com.alibaba.fastjson.annotation.JSONField;
import java.util.Date; import java.util.Map;
public class Goods { private int id; private String title; private double price; private int stock; private int saleNum; private Date createTime; private String categoryName; private String brandName; private Map spec;
@JSONField(serialize = false) private String specStr;
}
|
创建 dao
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.atguigu.mapper;
import com.atguigu.domain.Goods; import org.apache.ibatis.annotations.Mapper; import org.springframework.stereotype.Repository;
import java.util.List;
@Repository @Mapper public interface GoodsMapper {
public List<Goods> findAll();
}
|
在 resource
文件夹下面创建 mapper/GoodMapper.xml
配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mapper.GoodsMapper"> <select id="findAll" resultType="goods"> select `id` , `title` , `price` , `stock` , `saleNum` , `createTime` , `categoryName`, `brandName` , `spec` as specStr
from goods </select>
</mapper>
|
添加测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| @Autowired private GoodsMapper goodsMapper;
@Test public void importData() throws IOException { List<Goods> goodsList = goodsMapper.findAll();
BulkRequest bulkRequest = new BulkRequest();
for (Goods goods : goodsList) { String specStr = goods.getSpecStr(); Map map = JSON.parseObject(specStr, Map.class); goods.setSpec(map); String data = JSON.toJSONString(goods); IndexRequest indexRequest = new IndexRequest("goods"); indexRequest.id(goods.getId() + "").source(data, XContentType.JSON); bulkRequest.add(indexRequest); } BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT); System.out.println(response.status()); }
|
13、查询所有 matchAll 查询
matchAll 查询:查询所有文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
@Test public void testMatch() throws IOException { SearchRequest searchRequest = new SearchRequest("goods"); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); QueryBuilder query = QueryBuilders.matchAllQuery(); sourceBuilder.query(query); searchRequest.source(sourceBuilder); sourceBuilder.from(0); sourceBuilder.size(20); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); SearchHits searchHits = searchResponse.getHits(); long value = searchHits.getTotalHits().value; List<Goods> goodsList = new ArrayList<>(); SearchHit[] hits = searchHits.getHits(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString(); Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods); }
for (Goods goods : goodsList) { System.out.println(goods); } }
|
14、term 查询
term 查询:不会对查询条件进行分词。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
@Test public void testTermQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
QueryBuilder query = QueryBuilders.termQuery("title", "华为"); sourceBulider.query(query);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits(); long value = searchHits.getTotalHits().value; System.out.println("总记录数:" + value);
List<Goods> goodsList = new ArrayList<>(); SearchHit[] hits = searchHits.getHits(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString();
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods); }
for (Goods goods : goodsList) { System.out.println(goods); } }
|
15、matchQuery:词条分词查询
match 查询:
- 会对查询条件进行分词。
- 然后将分词后的查询条件和词条进行等值匹配
- 默认取并集(OR)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
@Test public void testMatchQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
MatchQueryBuilder query = QueryBuilders.matchQuery("title", "华为手机"); query.operator(Operator.AND); sourceBulider.query(query);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits(); long value = searchHits.getTotalHits().value; System.out.println("总记录数:" + value);
List<Goods> goodsList = new ArrayList<>(); SearchHit[] hits = searchHits.getHits(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString();
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods); }
for (Goods goods : goodsList) { System.out.println(goods); } }
|
16、模糊查询-脚本
- wildcard 查询:会对查询条件进行分词。还可以使用通配符 ?(任意单个字符) 和 * (0 个或多个字符)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
|
@Test public void testWildcardQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
WildcardQueryBuilder query = QueryBuilders.wildcardQuery("title", "华*");
sourceBulider.query(query);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits(); long value = searchHits.getTotalHits().value; System.out.println("总记录数:" + value);
List<Goods> goodsList = new ArrayList<>(); SearchHit[] hits = searchHits.getHits(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString();
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods); }
for (Goods goods : goodsList) { System.out.println(goods); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
@Test public void testPrefixQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
PrefixQueryBuilder query = QueryBuilders.prefixQuery("brandName", "华");
sourceBulider.query(query);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits(); long value = searchHits.getTotalHits().value; System.out.println("总记录数:" + value);
List<Goods> goodsList = new ArrayList<>(); SearchHit[] hits = searchHits.getHits(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString();
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods); }
for (Goods goods : goodsList) { System.out.println(goods); } }
|
17、范围查询-脚本
range 范围查询:查找指定字段在指定范围内包含值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
@Test public void testRangeQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
RangeQueryBuilder query = QueryBuilders.rangeQuery("price");
query.gte(2000); query.lte(3000);
sourceBulider.query(query);
sourceBulider.sort("price", SortOrder.DESC);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits(); long value = searchHits.getTotalHits().value; System.out.println("总记录数:" + value);
List<Goods> goodsList = new ArrayList<>(); SearchHit[] hits = searchHits.getHits(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString();
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods); }
for (Goods goods : goodsList) { System.out.println(goods); } }
|
18、queryString 查询-脚本
queryString:
- 会对查询条件进行分词。
- 然后将分词后的查询条件和词条进行等值匹配
- 默认取并集(OR)
- 可以指定多个查询字段
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
@Test public void testQueryStringQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
QueryStringQueryBuilder query = QueryBuilders.queryStringQuery("华为手机") .field("title") .field("categoryName") .field("brandName") .defaultOperator(Operator.AND);
sourceBulider.query(query);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits(); long value = searchHits.getTotalHits().value; System.out.println("总记录数:" + value);
List<Goods> goodsList = new ArrayList<>(); SearchHit[] hits = searchHits.getHits(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString();
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods); }
for (Goods goods : goodsList) { System.out.println(goods); } }
|
19、布尔查询
boolQuery:对多个查询条件连接。连接方式:
- must(and):条件必须成立
- must_not(not):条件必须不成立
- should(or):条件可以成立
- filter:条件必须成立,性能比 must 高。不会计算得分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
|
@Test public void testBoolQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
BoolQueryBuilder query = QueryBuilders.boolQuery();
QueryBuilder termQuery = QueryBuilders.termQuery("brandName", "华为"); query.must(termQuery);
QueryBuilder matchQuery = QueryBuilders.matchQuery("title", "手机"); query.filter(matchQuery);
QueryBuilder rangeQuery = QueryBuilders.rangeQuery("price"); ((RangeQueryBuilder) rangeQuery).gte(2000); ((RangeQueryBuilder) rangeQuery).lte(3000); query.filter(rangeQuery);
sourceBulider.query(query);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits(); long value = searchHits.getTotalHits().value; System.out.println("总记录数:" + value);
List<Goods> goodsList = new ArrayList<>(); SearchHit[] hits = searchHits.getHits(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString();
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods); }
for (Goods goods : goodsList) { System.out.println(goods); } }
|
20、聚合查询
- 指标聚合:相当于 MySQL 的聚合函数。max、min、avg、sum 等
- 桶聚合:相当于 MySQL 的 group by 操作。不要对 text 类型的数据进行分组,会失败。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
|
@Test public void testAggQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
MatchQueryBuilder query = QueryBuilders.matchQuery("title", "手机");
sourceBulider.query(query);
AggregationBuilder agg = AggregationBuilders.terms("goods_brands").field("brandName").size(100); sourceBulider.aggregation(agg);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits(); long value = searchHits.getTotalHits().value; System.out.println("总记录数:" + value);
List<Goods> goodsList = new ArrayList<>(); SearchHit[] hits = searchHits.getHits(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString();
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
goodsList.add(goods); }
for (Goods goods : goodsList) { System.out.println(goods); }
Aggregations aggregations = searchResponse.getAggregations();
Map<String, Aggregation> aggregationMap = aggregations.asMap();
Terms goods_brands = (Terms) aggregationMap.get("goods_brands");
List<? extends Terms.Bucket> buckets = goods_brands.getBuckets();
List brands = new ArrayList(); for (Terms.Bucket bucket : buckets) { Object key = bucket.getKey(); brands.add(key); }
for (Object brand : brands) { System.out.println(brand); } }
|
21、高亮查询
高亮三要素:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
@Test public void testHighLightQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("goods");
SearchSourceBuilder sourceBulider = new SearchSourceBuilder();
MatchQueryBuilder query = QueryBuilders.matchQuery("title", "手机");
sourceBulider.query(query);
HighlightBuilder highlighter = new HighlightBuilder(); highlighter.field("title"); highlighter.preTags("<font color='red'>"); highlighter.postTags("</font>");
sourceBulider.highlighter(highlighter);
AggregationBuilder agg = AggregationBuilders.terms("goods_brands").field("brandName").size(100); sourceBulider.aggregation(agg);
searchRequest.source(sourceBulider);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits(); long value = searchHits.getTotalHits().value; System.out.println("总记录数:"+value);
List<Goods> goodsList = new ArrayList<>(); SearchHit[] hits = searchHits.getHits(); for (SearchHit hit : hits) { String sourceAsString = hit.getSourceAsString();
Goods goods = JSON.parseObject(sourceAsString, Goods.class);
Map<String, HighlightField> highlightFields = hit.getHighlightFields(); HighlightField HighlightField = highlightFields.get("title"); Text[] fragments = HighlightField.fragments(); goods.setTitle(fragments[0].toString());
goodsList.add(goods); }
for (Goods goods : goodsList) { System.out.println(goods); } }
|
22、重建索引
随着业务需求的变更,索引的结构可能发生改变。
ElasticSearch 的索引一旦创建,只允许添加字段,不允许改变字段。因为改变字段,需要重建倒排索引,影响内部缓
存结构,性能太低。
那么此时,就需要重建一个新的索引,并将原有索引的数据导入到新索引中。
原索引库 :student_index_v1
新索引库 :student_index_v2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| # 新建student_index_v1索引,索引名称必须全部小写 PUT student_index_v1 { "mappings": { "properties": { "birthday":{ "type": "date" } } } } # 查询索引 GET student_index_v1 # 添加数据 PUT student_index_v1/_doc/1 { "birthday":"2021-11-11" } # 查询数据 GET student_index_v1/_search # 随着业务的变更,换种数据类型进行添加数据,程序会直接报错 PUT student_index_v1/_doc/1 { "birthday":"2021年11月11号" } # 业务变更,需要改变birthday数据类型为text # 1:创建新的索引 student_index_v2 # 2:将student_index_v1 数据拷贝到 student_index_v2
# 创建新的索引 PUT student_index_v2 { "mappings": { "properties": { "birthday":{ "type": "text" } } } }
DELETE student_index_v2
# 2:将student_index_v1 数据拷贝到 student_index_v2 POST _reindex { "source": { "index": "student_index_v1" }, "dest": { "index": "student_index_v2" } }
# 查询新索引库数据 GET student_index_v2/_search
# 在新的索引库里面添加数据 PUT student_index_v2/_doc/2 { "birthday":"2021年11月13号" }
|