Elasticsearch 7.X SpringBoot uses ElasticsearchRestTemplate to operate ES

1, ElasticsearchRestTemplate

Previously, I learned how the es rest interface operates es, and also learned the fragmentation and capacity expansion of ES. I explained several common word splitters. If you like, you can see other articles in this column. This article will mainly use ElasticsearchRestTemplate to operate es in SpringBoot.

I wrote an article on the operation of SpringBoot on ES long ago, but it was based on ES 6 X is not recommended in the new version of ES.

Note: some online tutorials use TransportClient for operation. TransportClient is not recommended in Elasticsearch 7.0, and TransportClient will be completely deleted in 8.0. Therefore, the official recommends that we use the Java High Level REST Client, which executes HTTP requests rather than serialized Java requests.

The ElasticsearchRestTemplate we use is another layer of encapsulation based on RestHighLevelClient. Let's start together.

2, SpringBoot integrates ES client environment

First, create a new SpringBoot project, and then introduce es dependency into pom:

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

In application In the YML configuration file, configure the connection of es:

server:
  port: 8080

spring:
  elasticsearch:
    rest:
      uris: http://127.0.0.1:9200 # multiple addresses are separated by commas
#      username:     #user name
#      password:     #password
      connection-timeout: 6000
      read-timeout: 6000

Now that the environment has been set up, let's start to operate es.

3, ElasticsearchRestTemplate operation ES

First, create an ES entity class:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "user", shards = 3, replicas = 1, refreshInterval = "30s")
public class UserEsEntity {
    @Id
    private String id;
    @Field(type = FieldType.Text, searchAnalyzer = "ik_max_word", analyzer = "ik_smart")
    private String name;
    @Field(type = FieldType.Keyword)
    private String sex;
    @Field(type = FieldType.Integer)
    private Integer age;
    @Field(type = FieldType.Keyword, index = false)
    private String grade;
}

The defined index name is user, the partition is 3, the copy of each partition is 1, and the refresh time is 30s.

Next, you can create an ElasticsearchRepository. In fact, you can directly use ElasticsearchRestTemplate to operate es, and many methods in the Repository are marked obsolete. Here you can also see:

@Repository
public interface UserEsDao extends ElasticsearchRepository<UserEsEntity, Long> {
}


ElasticsearchRepository is no longer recommended for queries. Let's learn the Api of ElasticsearchRestTemplate directly.

1. Judge whether the index exists

In fact, the Entity is written above. If the index does not exist, it will be created automatically. Here, you can also verify it through Api:

@Slf4j
@RestController
@RequestMapping("/rest")
public class RestTemplateController {
    @Autowired
    ElasticsearchRestTemplate elasticsearchRestTemplate;

    @GetMapping("/indexExists")
    public String indexExists() {
        boolean r1 = elasticsearchRestTemplate.indexExists(UserEsEntity.class);
        boolean r2 = elasticsearchRestTemplate.indexExists("user2");
//		Create index
//      elasticsearchRestTemplate.createIndex()
        log.info("r1: {} , r2: {}", r1, r2);
        return "success";
    }
}

2. Add document data

  @GetMapping("/save")
    public String save() {
        UserEsEntity esEntity = new UserEsEntity(null, "Zhang San", "male", 18, "1");

//        Don't get the self increasing return value
//        UserEsEntity save = elasticsearchRestTemplate.save(esEntity);
//        log.info(save.toString());

//        Get the self increasing return value
        IndexQuery indexQuery = new IndexQueryBuilder()
//                .withId(esEntity.getId())
                .withObject(esEntity)
                .build();
        String id = elasticsearchRestTemplate.index(indexQuery, IndexCoordinates.of("user"));
        log.info("Added id: {} ", id);

//        Batch add
//        List<UserEsEntity> list = new ArrayList<>();
//        list.add(esEntity);
//        list.add(esEntity);
//        elasticsearchRestTemplate.save(list);
        return "success";
    }

3. Update document data

For batch modification according to conditions, RestHighLevelClient needs to be used, which can be injected directly:

@Autowired
RestHighLevelClient restHighLevelClient;
    @GetMapping("/update")
    public String update() throws IOException {
//        Overwrite modification
//        Useresentity: esentity = new useresentity ("w9mvd34bvynyxunr8cde", "Lisi", "male", 20, "1");
//        elasticsearchRestTemplate.save(esEntity);
//        UpdateQuery query = UpdateQuery.builder("W9MVD34BVYNyxUnr8cdE");

//        Modify a field by ID
//        Document document = Document.create();
//        document.putIfAbsent("name", "wangwu2"); // Updated content
//        UpdateQuery updateQuery = UpdateQuery.builder("W9MVD34BVYNyxUnr8cdE")
//                .withDocument(document)
//                . withRetryOnConflict(5) / / conflict retry
//                . withDocAsUpsert(true) / / no default false. True indicates to insert when the update does not exist
//                .build();
//        UpdateResponse response = elasticsearchRestTemplate.update(updateQuery, IndexCoordinates.of("user"));
//        log.info(response.getResult().toString()); //UPDATED indicates that the update was successful


//       Batch update according to conditions and use RestHighLevelClient
//        https://blog.csdn.net/weixin_34318272/article/details/88690004
//        The parameter is an index name, which can be unspecified, one or more
        UpdateByQueryRequest request = new UpdateByQueryRequest("user");
//        Version conflict
        request.setConflicts("proceed");
//        Set query criteria
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
//        And and
        queryBuilder.must(QueryBuilders.termQuery("name", "lisi"));
        queryBuilder.must(QueryBuilders.termQuery("sex", "male"));
        request.setQuery(queryBuilder);
//        Batch size
        request.setBatchSize(1000);
//        parallel
        request.setSlices(2);
//        Use the scroll parameters to control how long the search context survives
        request.setScroll(TimeValue.timeValueMinutes(10));
//        Refresh index
        request.setRefresh(true);
//        Updated content
        request.setScript(new Script("ctx._source['name']='wangwu'"));
        BulkByScrollResponse response = restHighLevelClient.updateByQuery(request, RequestOptions.DEFAULT);
        log.info(response.getStatus().getUpdated() + ""); // A return of 1 indicates success
        return "success";
    }

4. Delete document data

    @GetMapping("/delete")
    public String delete() {
//        Delete by id
//        String r = elasticsearchRestTemplate.delete("XNMVD34BVYNyxUnr8cdE", IndexCoordinates.of("user"));
//        log.info("r : {} ", r);

//        Delete according to condition
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
//        And and
        queryBuilder.must(QueryBuilders.termQuery("name", "zhangsan"));
        queryBuilder.must(QueryBuilders.termQuery("sex", "male"));
        Query query = new NativeSearchQuery(queryBuilder);
        elasticsearchRestTemplate.delete(query, UserEsEntity.class, IndexCoordinates.of("user"));

        return "success";
    }

5. Query document data

    @GetMapping("/search")
    public String search() {
//        Query all data
//        QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();

//        Precise query=
//        QueryBuilder queryBuilder = QueryBuilders.termQuery("name", "lisi");

//        Accurately query multiple in
//        QueryBuilder queryBuilder = QueryBuilders.termsQuery("name", "Zhang San", "lisi");

//        match matching will segment the query criteria, and then query. Multiple entries have an or relationship, and word segmentation can be specified
//        QueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "Zhang San");
//        QueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "Zhang San") analyzer("ik_max_word");

//        match query multiple fields
//        QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("male", "name", "sex");

//        Fuzzy fuzzy query, which returns documents containing words similar to the search words.
//        QueryBuilder  queryBuilder = QueryBuilders.fuzzyQuery("name","lisx");

//        Prefix prefix retrieval
//        QueryBuilder  queryBuilder = QueryBuilders.prefixQuery("name", "Zhang");

//        Wildcard wildcard retrieval
//        QueryBuilder  queryBuilder = QueryBuilders.wildcardQuery("name", "Zhang *");

//        regexp regular query
        QueryBuilder queryBuilder = QueryBuilders.regexpQuery("name", "(Zhang San)|(lisi)");
        
//        boost score weight, which makes the score of documents that meet a certain condition higher, so as to make them rank higher.
        queryBuilder.boost(2);
//        Multi conditional construction
//        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
//        And and
//        queryBuilder.must(QueryBuilders.termQuery("name", "Zhang San");
//        queryBuilder.must(QueryBuilders.termQuery("sex", "female");

//        or
//        queryBuilder.should(QueryBuilders.termQuery("name", "Zhang San"));
//        queryBuilder.should(QueryBuilders.termQuery("name", "lisi"));

//        Not equal to, remove
//        queryBuilder.mustNot(QueryBuilders.termQuery("name", "lisi"));

//        Filter data
//        queryBuilder.filter(QueryBuilders.matchQuery("name", "Zhang San");

//        Range query
        /*
            gt Greater than >
            gte Greater than or equal to >=
            lt Less than<
            lte Less than or equal to<=
        */
//        queryBuilder.filter(new RangeQueryBuilder("age").gt(10).lte(50));

//        Build page, page starts from 0
        Pageable pageable = PageRequest.of(0, 3);
        
        Query query = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withPageable(pageable)
                //sort
                .withSort(SortBuilders.fieldSort("_score").order(SortOrder.DESC))
                //Projection
                .withFields("name")
                .build();
        SearchHits<UserEsEntity> search = elasticsearchRestTemplate.search(query, UserEsEntity.class);
        log.info("total: {}", search.getTotalHits());
        Stream<SearchHit<UserEsEntity>> searchHitStream = search.get();
        List<UserEsEntity> list = searchHitStream.map(SearchHit::getContent).collect(Collectors.toList());
        log.info("Number of results:{}", list.size());
        list.forEach(entity -> {
            log.info(entity.toString());
        });
        return "success";
    }


Love little buddy can pay attention to my personal WeChat official account and get more learning materials.

Keywords: Java ElasticSearch search engine

Added by sh0wtym3 on Mon, 03 Jan 2022 10:01:46 +0200