编程语言
首页 > 编程语言> > ElasticSearch学习十 Java API操作ES

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查询:

 

 

 

 

 

代码

@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);
        }
​
    }

 

模糊查询

模糊查询有三种:

  1. 通配符查询(wildcard):会对查询条件进行分词。还可以使用通配符?(任意单个字符)和*(0或多个字符)

  2. regexp查询:正则查询

  3. 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查询:

脚本

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