Java实战 - ElasticsearchRestTemplate

说明: 本次演示版本:SpringBoot 2.4.1,Elasticsearch 7.6.1

一. 设置链接 - application.properties配置 - 方法2

# Elasticsearch 链接地址
// client方式连接
spring.data.elasticsearch.cluster-nodes=localhost:9200
spring.data.elasticsearch.cluster-name=my-application
// rest方式连接
spring.data.elasticsearch.rest.uris=http://localhost:9200
// 参考地址
https://blog.csdn.net/mingover/article/details/82941506
https://blog.csdn.net/weixin_41446608/article/details/109026527

二. 添加Maven依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

三. 通过@Document注解自动注入实体的索引名,便于后续个别使用

package com.example.spring_boot_demo.entity;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;

@Data
@Document(indexName = "hcode_index")
public class ElasticsearchEntity {

    /**
     * id (最好添加@Id注解,表明该字段是id)
     */
    @Id
    private Integer id;

    private String userName;

    private int age;

    public ElasticsearchEntity(Integer id,String userName,int age){
        this.id = id;
        this.userName = userName;
        this.age = age;
    }
}

四. 关于注解

1.通过 @Autowired 注解自动注入

@Autowired
private ElasticsearchRestTemplate esTemplate;

2.继承 ElasticsearchRepository 类(不用实现任何方法),在通过 @Resource 注解自动注入使用

//Long 是ID类型
public interface BankRepository extends ElasticsearchRepository<BankEntity,Long> {
}
@Resource
private BankRepository bankRepository;

五. 创建公共查询方法 - 便于后续查询使用

private void queryUtil(QueryBuilder queryBuilder) {
    System.out.println("------------- 分割线 ------------------");
        /* 分页查询方式 */
//        NativeSearchQueryBuilder searchQuery
//                                 = new NativeSearchQueryBuilder().withQuery(queryBuilder);
//        searchQuery.withPageable(PageRequest.of(1,10));
//        NativeSearchQuery search = searchQuery.build();

    // 创建查询对象
    NativeSearchQuery searchQuery
                       = new NativeSearchQueryBuilder().withQuery(queryBuilder).build();
    // 查询结果集并映射到指定的对象中
    SearchHits<StudentEntity> searchHits
                       = esTemplate.search(searchQuery,ElasticsearchEntity.class);
    // 单纯的迭代器输出
    Iterator<SearchHit<StudentEntity>> iterator = searchHits.iterator();
    while (iterator.hasNext()) {
        System.out.println("根据名称查找结果:" + iterator.next());
    }
}

六. ElasticsearchRestTemplate的后宫

1. 添加单条数据
//方法1:esTemplate.save(实体);
ElasticsearchEntity es = new ElasticsearchEntity(6, "李da鬼", 18);
esTemplate.save(es);
//方法2:bankRepository.save("数据集");
List<BankEntity> bankList = this.createData(dataSize);//有构建好的数据集
bankRepository.save(bankList);
2. 批量添加数据
// 方法1:esTemplate.bulkIndex(ArrayList<IndexQuery>,实体.class);
List<ElasticsearchEntity> esList = new ArrayList<>();
...
ArrayList<IndexQuery> indexQueries = new ArrayList<>();
for (ElasticsearchEntity esl:esList){
    IndexQuery indexQuery = new IndexQuery();
    indexQuery.setId(esl.getId().toString());
    indexQuery.setObject(esl);
    indexQueries.add(indexQuery);
    esTemplate.bulkIndex(indexQueries,ElasticsearchEntity.class);
}
// 方法2:bankRepository.saveAll("数据集");
List<BankEntity> bankList = this.createData(dataSize);//已构建好的数据
bankRepository.saveAll(bankList);
3. 根据id查询数据:
// 方法1:.get("id", 映射对象(实体).class);
ElasticsearchEntity elasticsearch = esTemplate.get(id, ElasticsearchEntity.class);
System.out.println("根据id查询ES中的数据集:" + elasticsearch.toString());
// 方法2:QueryBuilders.idsQuery().addIds(id/id[]);
IdsQueryBuilder idsQueryBuilder
                 = QueryBuilders.idsQuery().addIds(id);
NativeSearchQuery nativeSearchQuery
                 = new NativeSearchQueryBuilder().withQuery(idsQueryBuilder).build();
SearchHits<BankEntity> bank
                 = esRestTemplate.search(nativeSearchQuery,BankEntity.class);
4. 查询全部数据:
// 方法1:.search(Query.findAll(), 映射对象(实体).class); 只能查询到第一页的1条数据
SearchHits<ElasticsearchEntity> esHits
                            = esTemplate.search(Query.findAll(), ElasticsearchEntity.class);
//方法2:.matchAllQuery()
QueryBuilder queryBuilders = QueryBuilders.matchAllQuery();
NativeSearchQuery nativeSearchQuery
                   = new NativeSearchQueryBuilder().withQuery(queryBuilders).build();
SearchHits<BankEntity> bankSearch
                   = esRestTemplate.search(nativeSearchQuery,BankEntity.class);
5. 分词查询:.matchQuery(“字段名”, “参数”);
  • 会将搜索词分词,再与目标查询字段进行匹配,若分词中的任意一个词与目标字段匹配上,则可查询到
QueryBuilder queryBuilder = QueryBuilders.matchQuery(fieldName, condition);
queryUtil(queryBuilder);
6. 组合查询:termQuery 精确查询
// .must():AND,  .mustNot():NOT,  .should():OR
QueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery("userName", "李消"))
                .mustNot(QueryBuilders.termQuery("age", "18"))
                .should(QueryBuilders.termQuery("userName", "ydouth"));
queryUtil(queryBuilder);
  • 注意:term做精确查询可以用它来处理数字(numbers)、布尔值(Booleans)、日期(dates)以及文本(text)。查询数字时问题不大,但是当查询字符串时会有问题。term查询的含义是termQuery会去倒排索引中寻找确切的term,但是它并不知道分词器的存在。term表示查询字段里含有某个关键词的文档,terms表示查询字段里含有多个关键词的文档。也就是说直接对字段进行term本质上还是模糊查询,只不过不会对搜索的输入字符串进行分词处理罢了。如果想通过term查到数据,那么term查询的字段在索引库中就必须有与term查询条件相同的索引词,否则无法查询到结果。
  • 一句话解释: elasticsearch 里默认的IK分词器是会将每一个中文都进行了分词的切割,所以你直接想查一整个词,或者一整句话是无返回结果的。
  • 解决方案:

    ① 将字段的type设置为keyword
    ② 将该字段设置成 not_analyzed 无需分析的
    ③ 参考网址:https://zhuanlan.zhihu.com/p/270426807https://blog.csdn.net/u011821334/article/details/100979286

7. 一次匹配多个值termsQuery 多term查询: .termsQuery(“字段名”, “参数1”, “参数2”,…);
QueryBuilder queryBuilder = QueryBuilders.termsQuery(fieldName, condition, conditionTwo);
queryUtil(queryBuilder);
8. 查询解析,查询字符串,不需要指定字段(精准匹配):.queryStringQuery(“参数”);
QueryBuilder queryBuilder = QueryBuilders.queryStringQuery(condition);
queryUtil(queryBuilder);
9. 通配符查询, 支持星号, 匹配任何字符序列, 包括空, 避免* 开始, 会检索大量内容造成效率缓慢
//.wildcardQuery("字段名", "参数*" || "*参数" || "*参数*");
QueryBuilder queryBuilder = QueryBuilders.wildcardQuery(fieldName, condition);
queryUtil(queryBuilder);
10. 范围查询
// .rangeQuery("字段名").from("参数1").to("参数2").includeLower(true).includeUpper(true);
QueryBuilder queryBuilder = QueryBuilders.rangeQuery("age").from("11").to("22")
                .includeLower(true) //是否包含from()中的参数
                .includeUpper(true); //是否包含to()中的参数
queryUtil(queryBuilder);
11. 模糊查询
// .fuzzyQuery("字段名","参数");
QueryBuilder queryBuilder = QueryBuilders.fuzzyQuery(field, parameters);
queryUtil(queryBuilder);

12. 修改数据

Document document = Document.create();
document.setId("id");
document.put("字段名", "要修改的值");
UpdateQuery build = UpdateQuery.builder("id").withDocument(document).withScriptedUpsert(true).build();
restTemplate.update(build, IndexCoordinates.of("索引名"));

13. 删除索引

参考地址

参考地址:
https://www.cnblogs.com/sbj-dawn/p/8891526.html
https://blog.csdn.net/lifePracticer/article/details/109820553
ES优化:
https://www.cnblogs.com/linwenbin/p/13390584.html
实战:
https://blog.csdn.net/csdn_20150804/article/details/105618933