ElasticSearch学习十 Java API操作ES
作者:互联网
十、Java API操作ES
10.1、Springboot整合ES
导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.haojie</groupId>
<artifactId>elasticsearch</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>elasticsearch</name>
<description>elasticsearch</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--es-->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.4.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.4.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
编写配置类
package com.haojie.elasticsearch.config;
import lombok.Data;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties("elasticsearch")
@Data
public class ElasticSearchConfig {
private String hosts;
@Bean
public RestHighLevelClient restHighLevelClient(){
String[] hostArr=hosts.split(",");
HttpHost[] httpHosts=new HttpHost[hostArr.length];
for(int i=0;i<hostArr.length;i++){
String host=hostArr[i];
String[] hostTempArr = host.split(":");
String ip=hostTempArr[0];
Integer port=Integer.parseInt(hostTempArr[1]);
httpHosts[i]=new HttpHost(ip,port,"http");
}
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
httpHosts
));
return client;
}
}
10.2、操作索引
添加索引
单纯的添加索引
@Test
public void addIndex() throws IOException {
// indices是index的复数
IndicesClient indicesClient = restHighLevelClient.indices();
// 具体操作,获取返回值
CreateIndexRequest createIndexRequest = new CreateIndexRequest("itheima");
CreateIndexResponse createIndexResponse = indicesClient.create(createIndexRequest, RequestOptions.DEFAULT);
// 判断返回值结果
System.out.println(createIndexResponse.isAcknowledged());
}
创建带数据类型的索引
@Test
public void addIndexAndMapping() throws IOException {
// indices是index的复数
IndicesClient indicesClient = restHighLevelClient.indices();
// 具体操作,获取返回值
CreateIndexRequest createIndexRequest = new CreateIndexRequest("itcast");
String mappingStr="{\"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" +
" }}";
createIndexRequest.mapping(mappingStr, XContentType.JSON);
CreateIndexResponse createIndexResponse = indicesClient.create(createIndexRequest, RequestOptions.DEFAULT);
// 判断返回值结果
System.out.println(createIndexResponse.isAcknowledged());
}
查询索引
@Test
public void getIndexAndMapping() throws IOException {
IndicesClient indicesClient = restHighLevelClient.indices();
GetIndexRequest getIndexRequest=new GetIndexRequest("itcast");
GetIndexResponse getIndexResponse = indicesClient.get(getIndexRequest, RequestOptions.DEFAULT);
Map<String, MappingMetaData> mappings = getIndexResponse.getMappings();
for(String key:mappings.keySet()){
System.out.println(key+"="+mappings.get(key).getSourceAsMap());
}
}
删除索引
@Test
public void deleteIndex() throws IOException {
IndicesClient indicesClient = restHighLevelClient.indices();
DeleteIndexRequest deleteIndexRequest=new DeleteIndexRequest("itheima");
AcknowledgedResponse acknowledgedResponse = indicesClient.delete(deleteIndexRequest, RequestOptions.DEFAULT);
System.out.println(acknowledgedResponse.isAcknowledged());
}
判断索引是否存在
/**
* 判断索引是否存在
* @throws IOException
*/
@Test
public void existIndex() throws IOException {
IndicesClient indicesClient = restHighLevelClient.indices();
GetIndexRequest getIndexRequest=new GetIndexRequest("itcast");
boolean exists = indicesClient.exists(getIndexRequest, RequestOptions.DEFAULT);
System.out.println(exists);
}
10.3、文档操作
添加文档
采取Map作为类型添加索引
/**
* 使用map作为数据
* @throws IOException
*/
@Test
public void addDoc() throws IOException {
Map<String,Object> data=new HashMap<>();
data.put("address","北京昌平");
data.put("age",35);
data.put("name","张三");
IndexRequest indexRequest=new IndexRequest("itcast").id("1").source(data);
// 添加数据 获取结果
IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(indexResponse.getId());
}
普通对象添加
/**
* 使用对象作为数据
* @throws IOException
*/
@Test
public void addDocObj() throws IOException {
Person person=new Person();
person.setId("2");
person.setAddress("浙江萧山");
person.setAge(20);
person.setName("李四");
// 将对象转成json
String data=JSONObject.toJSONString(person);
System.out.println(data);
IndexRequest indexRequest=new IndexRequest("itcast").id(person.getId()).source(data,XContentType.JSON);
// 添加数据 获取结果
IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(indexResponse.getId());
}
修改文档
/**
* id存在则修改,id不存在则添加
* @throws IOException
*/
@Test
public void updateObj() throws IOException {
Person person=new Person();
person.setId("2");
person.setAddress("浙江萧山");
person.setAge(20);
person.setName("李四222");
// 将对象转成json
String data=JSONObject.toJSONString(person);
System.out.println(data);
IndexRequest indexRequest=new IndexRequest("itcast").id(person.getId()).source(data,XContentType.JSON);
// 添加数据 获取结果
IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
System.out.println(indexResponse.getId());
}
查询文档
/**
根据id查询文档
*/
@Test
public void findDocById() throws IOException {
GetRequest getRequest=new GetRequest("itcast");
getRequest.id("1");
GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
System.out.println(getResponse.getSourceAsString());
}
删除文档
/**
* 根据id删除文档
* @throws IOException
*/
@Test
public void deleteDocById() throws IOException {
DeleteRequest deleteRequest=new DeleteRequest("itcast","1");
DeleteResponse delete = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(delete.getId());
}
10.4、批量操作
脚本
bulk 批量操作就是将文档的增删改查一系列操作,通过一次请求全部完成,减少网络传输次数。
语法:
POST /_bulk
{"action":{"metadata"}}
{"data"}
action:代表这个操作是什么操作,delete、update等等
metadata:代表元数据,操作的数据是那个索引、或者索引的id等
data:是操作的具体数据
元数据与数据之间不能换行
示例:
POST /_bulk
{"delete":{"_index":"person","_id":"5"}}
{"create":{"_index":"person","_id":"5"}}
{"name":"六号","age":20,"address":"北京"}
{"update":{"_index":"person","_id":"2"}}
{"doc":{"name":"二号"}}
POST /_bulk
{"delete":{"_index":"person","_id":"5"}}
{"create":{"_index":"person","_id":"6"}}
{"name":"俞敏洪","address":"北京海淀"}
{"update":{"_index":"person","_id":"6"}}
{"doc":{"name":"老罗"}}
代码
@Test
public void testBulk() throws IOException {
// 创建bulkRequest ,用于整合所有操作
BulkRequest bulkRequest=new BulkRequest();
// 删除1号记录
DeleteRequest deleteRequest=new DeleteRequest("person","1");
bulkRequest.add(deleteRequest);
// 添加8号记录
Map<String,Object> map=new HashMap<>();
map.put("name","八号");
IndexRequest indexRequest=new IndexRequest("person").id("8").source(map);
bulkRequest.add(indexRequest);
//更新3号
Map<String,Object> map2=new HashMap<>();
map2.put("name","三号");
UpdateRequest updateRequest=new UpdateRequest("person","3").doc(map2);
bulkRequest.add(updateRequest);
//执行
restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
}
10.5、导入数据
数据准备
表结构
CREATE TABLE `goods` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`author` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
`desc` varchar(255) DEFAULT NULL,
`create_time` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11265 DEFAULT CHARSET=utf8;
elasticsearch 中索引的创建
PUT goods
{
"mappings": {
"properties": {
"name":{
"type": "keyword"
},
"author":{
"type": "keyword"
},
"address":{
"type":"object"
},
"desc":{
"type": "text",
"analyzer":"ik_smart"
},
"createTime":{
"type": "date"
}
}
}
}
代码
批量添加的代码
@Test
public void importData() throws IOException {
List<Goods> goodsList = goodsMapper.qryAll();
BulkRequest bulkRequest=new BulkRequest();
for(Goods goods:goodsList){
IndexRequest indexRequest=new IndexRequest("goods");
// 在elasticsearch中,address字段是Object类,因此java中的address字段需要是对象
// 因此需要把addressStr这个json类型的字符串转成Map对象
goods.setAddress(JSONObject.parseObject(goods.getAddressStr(),Map.class));
indexRequest.id(goods.getId()+"").source(JSONObject.toJSONString(goods),XContentType.JSON);
bulkRequest.add(indexRequest);
}
restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
}
结果
{
"_index" : "goods",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"address" : {
"province" : "河南",
"city" : "郑州"
},
"addressStr" : """{"province":"河南","city":"郑州"}""",
"author" : "测试数据",
"id" : 1,
"name" : "华为手机",
"remark" : "北京"
}
}
其实在es中,一般不需要addressStr字段,那么在用fastjson进行序列化时,把这个字段不序列化就行了
package com.haojie.elasticsearch.model;
import java.io.Serializable;
import java.util.Date;
import java.util.Map;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
/**
* goods
* @author
*/
@Data
public class Goods implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private String author;
private Map<String,Object> address;
@JSONField(serialize = false)
private String addressStr;
private String remark;
private Date createTime;
}
10.6、复杂查询
matchAll查询
脚本
matchAll查询:查询所有数据,默认查询只有10条
GET goods/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 200
}
结果分析
代码
@Test
public void matchAllQry() throws IOException {
// 构建查询对象,指定查询索引名称
SearchRequest searchRequest=new SearchRequest("goods");
// 设置查询条件
SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
QueryBuilder query= QueryBuilders.matchAllQuery();
sourceBuilder.query(query);
searchRequest.source(sourceBuilder);
//执行查询
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
TotalHits totalHits = searchHits.getTotalHits();
System.out.println(totalHits.value);
SearchHit[] hits = searchHits.getHits();
List<Goods> goodsList=new ArrayList<>();
for(SearchHit hit:hits){
String sourceAsString = hit.getSourceAsString();
Goods goods = JSONObject.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
System.out.println(goods);
}
}
term查询
term不会对查询条件进行分词。采用的是等于查询以及字段是keyword的字段。查询语法
脚本
代码
@Test
public void termQuery() throws IOException {
SearchRequest searchRequest=new SearchRequest("goods");
SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "华为");
sourceBuilder.query(termQueryBuilder);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
TotalHits totalHits = searchHits.getTotalHits();
System.out.println(totalHits.value);
SearchHit[] hits = searchHits.getHits();
List<Goods> goodsList=new ArrayList<>();
for(SearchHit hit:hits){
String sourceAsString = hit.getSourceAsString();
Goods goods = JSONObject.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
System.out.println(goods);
}
}
match查询
脚本
match查询:
-
会对查询条件进行分词
-
然后将分词后的查询条件和索引中的字段进行等值匹配
-
默认取并集(OR)
代码
@Test
public void matchQuery() throws IOException {
SearchRequest searchRequest=new SearchRequest("goods");
SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", "华为");
matchQueryBuilder.operator(Operator.AND);
sourceBuilder.query(matchQueryBuilder);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
TotalHits totalHits = searchHits.getTotalHits();
System.out.println(totalHits.value);
SearchHit[] hits = searchHits.getHits();
List<Goods> goodsList=new ArrayList<>();
for(SearchHit hit:hits){
String sourceAsString = hit.getSourceAsString();
Goods goods = JSONObject.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
System.out.println(goods);
}
}
模糊查询
模糊查询有三种:
-
通配符查询(wildcard):会对查询条件进行分词。还可以使用通配符?(任意单个字符)和*(0或多个字符)
-
regexp查询:正则查询
-
prefix查询:前缀查询
脚本
代码
@Test
public void wildcardQuery() throws IOException {
SearchRequest searchRequest=new SearchRequest("goods");
SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery("name", "华为*");
sourceBuilder.query(wildcardQueryBuilder);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
TotalHits totalHits = searchHits.getTotalHits();
System.out.println(totalHits.value);
SearchHit[] hits = searchHits.getHits();
List<Goods> goodsList=new ArrayList<>();
for(SearchHit hit:hits){
String sourceAsString = hit.getSourceAsString();
Goods goods = JSONObject.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
System.out.println(goods);
}
}
范围查询
range范围查询:查询指定字段在指定范围内
脚本
代码
@Test
public void rangeQuery() throws IOException {
SearchRequest searchRequest=new SearchRequest("goods");
SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
// 范围
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("id");
// 下限
rangeQueryBuilder.gt(10);
// 上限
rangeQueryBuilder.lt(16);
sourceBuilder.query(rangeQueryBuilder);
// 进行排序 所有查询都可以排序
sourceBuilder.sort("id", SortOrder.DESC);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
TotalHits totalHits = searchHits.getTotalHits();
System.out.println(totalHits.value);
SearchHit[] hits = searchHits.getHits();
List<Goods> goodsList=new ArrayList<>();
for(SearchHit hit:hits){
String sourceAsString = hit.getSourceAsString();
Goods goods = JSONObject.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
System.out.println(goods);
}
}
queryString查询
queryString查询:
-
会对查询条件进行分词
-
然后将分词后的查询条件和索引中的文档字段进行等值匹配
-
默认取并集(or)
-
可以指定多个查询字段
脚本
GET 索引名称/_search
{
"query": {
"query_string": {
"fields": ["字段1","字段2"],
"query": "查询条件"
}
}
}
GET goods/_search
{
"query": {
"query_string": {
"fields": ["author","remark","name"],
"query": "华为"
}
}
}
GET goods/_search
{
"query": {
"query_string": {
"fields": ["author","remark","name"],
"query": "华为 OR 测试"
}
}
}
逻辑运算符要大写
代码
@Test
public void queryStringQuery() throws IOException {
SearchRequest searchRequest=new SearchRequest("goods");
SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
// queryString
QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery("华为手机").field("name").field("authro").defaultOperator(Operator.AND);
sourceBuilder.query(queryStringQueryBuilder);
// 进行排序 所有查询都可以排序
sourceBuilder.sort("id", SortOrder.DESC);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
TotalHits totalHits = searchHits.getTotalHits();
System.out.println(totalHits.value);
SearchHit[] hits = searchHits.getHits();
List<Goods> goodsList=new ArrayList<>();
for(SearchHit hit:hits){
String sourceAsString = hit.getSourceAsString();
Goods goods = JSONObject.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
System.out.println(goods);
}
}
布尔查询
boolQuery:对多个查询条件进行连接
must(and): 条件必须成立
must_not(not):条件必须不成立
should(or):条件可以成立
filter:条件必须成立,性能比must高,不会计算得分。
脚本
GET goods/_search
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "华为电脑"
}
}
},
{
"match": {
"remark": "成都"
}
}
]
}
}
}
因此must会计算得分,因此性能会比较慢,如果第一个条件用来must,建议后面的条件采用filter,filter不会计算得分。
GET goods/_search
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "华为电脑"
}
}
},
{
"match": {
"remark": "成都"
}
}
],
"filter": {
"term": {
"author": "测试"
}
}
}
}
}
GET goods/_search
{
"query": {
"bool": {
"must": [
{"term": {
"name": {
"value": "华为电脑"
}
}
},
{
"match": {
"remark": "成都"
}
}
],
"filter": [
{
"term":{
"author":{
"value":"测试"
}
}
}
]
}
}
}
聚合查询
指标聚合:相当于mysql中的聚合函数。max、min、avg、sum等。
桶聚合:相当于mysql的group by操作。不要对text类型的数据进行分组,会失败。text类型的数据需要分词,
脚本
查询所有name是华为电脑的文档,并且计算最大的id
GET goods/_search
{
"query": {
"match": {
"name": "华为电脑"
}
}
, "aggs": {
"max_id": {
"max": {
"field": "id"
}
}
}
}
结果
"aggregations" : {
"max_id" : {
"value" : 11260.0
}
}
对author进行分组,不能对remark字段进行分组,因为remark字段是text类型
GET goods/_search
{
"query": {
"match": {
"name": "华为电脑"
}
}, "aggs": {
"author_type": {
"terms": {
"field": "author",
"size": 10
}
}
}
}
结果
"aggregations" : {
"author_type" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "测试",
"doc_count" : 1024
},
{
"key" : "王五",
"doc_count" : 1
}
]
}
}
代码
@Test
public void aggQuery() throws IOException {
SearchRequest searchRequest=new SearchRequest("goods");
SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
// matchQuery
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name","华为电脑");
sourceBuilder.query(matchQueryBuilder);
// 进行聚合 分组
// 第一个参数是自定义名称,用于获取数据
// 第二个字段是进行聚合的字段
AggregationBuilder agg= AggregationBuilders.terms("author_type").field("author").size(100);
sourceBuilder.aggregation(agg);
// 查询请求与查询条件进行关联
searchRequest.source(sourceBuilder);
//执行查询
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
SearchHit[] hits = searchHits.getHits();
List<Goods> goodsList=new ArrayList<>();
for(SearchHit hit:hits){
String sourceAsString = hit.getSourceAsString();
Goods goods = JSONObject.parseObject(sourceAsString, Goods.class);
goodsList.add(goods);
System.out.println(goods);
}
// 获取聚合结果
Aggregations aggregations = searchResponse.getAggregations();
Map<String, Aggregation> stringAggregationMap = aggregations.asMap();
Terms brand_name = (Terms) stringAggregationMap.get("author_type");
List<? extends Terms.Bucket> buckets = brand_name.getBuckets();
for (Terms.Bucket bucket:buckets){
System.out.println(bucket.getKey());
}
}
高亮查询
高亮三要素:
-
高亮字段
-
前缀
-
后缀
脚本
GET goods/_search
{
"query": {
"match": {
"name": "华为电脑"
}
},
"highlight": {
"fields": {
"name": {
"pre_tags": "<font color='red'>",
"post_tags": "</font>"
}
}
}
}
结果:
{
"_index" : "goods",
"_type" : "_doc",
"_id" : "18",
"_score" : 2.3984714,
"_source" : {
"address" : {
"province" : "河南",
"city" : "郑州"
},
"author" : "测试",
"id" : 18,
"name" : "华为电脑",
"remark" : "成都"
},
"highlight" : {
"name" : [
"<font color='red'>华为电脑</font>"
]
}
},
代码
@Test
public void highLightQuery() throws IOException {
SearchRequest searchRequest=new SearchRequest("goods");
SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();
// matchQuery
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name","华为电脑");
sourceBuilder.query(matchQueryBuilder);
// 高亮设置
HighlightBuilder highlightBuilder=new HighlightBuilder();
highlightBuilder.field("name");
highlightBuilder.preTags("<font color='red'>");
highlightBuilder.postTags("</font>");
sourceBuilder.highlighter(highlightBuilder);
// 查询请求与查询条件进行关联
searchRequest.source(sourceBuilder);
//执行查询
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits searchHits = searchResponse.getHits();
SearchHit[] hits = searchHits.getHits();
List<Goods> goodsList=new ArrayList<>();
for(SearchHit hit:hits){
// 获取查询结果
String sourceAsString = hit.getSourceAsString();
Goods goods = JSONObject.parseObject(sourceAsString, Goods.class);
// 获取高亮结果
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField highlightField = highlightFields.get("name");
Text[] fragments = highlightField.fragments();
goods.setName(fragments[0].toString());
goodsList.add(goods);
System.out.println(goods);
}
}
10.7、索引别名和重新创建索引
随着业务需求的变更,索引的结构可能发生改变。
ElasticSearch的索引一旦创建,只运行添加字段,不运行改变字段。因为改变字段需要重建倒排索引,影响内部缓存结构,性能太低。
那么此时,就需要重新创建一个新的索引,并将原有索引的数据导入到新索引中。
新建student_index_v1。索引名称必须全部小写。索引名称必须全部小写。
如果索引包含大写字母,则会报错
有时候为了应对业务的变化,索引结构会变化,这个时候需要重新创建索引,需要把老的索引中的数据拷贝到新创建的索引中,可以采用一个命令 _reindex
脚本
PUT studnet_index_v1
{
"mappings": {
"properties": {
"name":{
"type": "keyword"
}
}
}
}
PUT /studnet_index_v1/_doc/1
{
"name":"张三"
}
PUT student_index_v2
{
"mappings": {
"properties": {
"name":{
"type": "text"
}
}
}
}
POST _reindex
{
"source": {
"index": "studnet_index_v1"
},
"dest": {
"index": "student_index_v2"
}
}
运行结果
{
"took" : 425,
"timed_out" : false,
"total" : 1,
"updated" : 0,
"created" : 1,
"deleted" : 0,
"batches" : 1,
"version_conflicts" : 0,
"noops" : 0,
"retries" : {
"bulk" : 0,
"search" : 0
},
"throttled_millis" : 0,
"requests_per_second" : -1.0,
"throttled_until_millis" : 0,
"failures" : [ ]
}
索引重建之后,虽然数据以及拷贝到了studnet_index_v2,但是代码中用的还是studnet_index_v1,因此需要对studnet_index_v2做一个别名。
首先删除索引student_index_v1
然后给索引student_index_v2起别名,别名叫student_index_v1
POST student_index_v2/_alias/student_index_v1 //给studnet_index_v2起别名
标签:index,goods,Java,name,查询,API,ElasticSearch,new,id 来源: https://www.cnblogs.com/cplinux/p/16412628.html