SpringBoot 使用 Rest api来操作ElasticSearch(使用接口做CRUD)

描述

上一篇写的只是针对es做普通的CRUD,这次采用接口做CRUD,如果是小白的话,可以查看我以往的ES文章。

依赖项

<properties>
    <java.version>1.8</java.version>
    <elasticsearch.version>6.8.12</elasticsearch.version>
</properties>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

操作

Entity实体

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

/**
 * springboot-es >>> 【cn.ityao.es.entity】
 *
 * @author: tongyao
 * @since: 2023-05-16 15:13
 */
@Data
@Document(indexName = "person_index", type = "person")
public class Person {
    
    

    @Id
    private String id;
    @Field(type = FieldType.Keyword)//手动设置为keyword  但同时也就不能分词
    private String name;
    @Field(type = FieldType.Auto)//自动检测类型
    private int age;
    @Field(type = FieldType.Text, analyzer = "ik_smart", searchAnalyzer = "ik_max_word")//设置为text  可以分词
    private String info;

}

Service,这里的Service需要继承一个CrudRepository类,<对应实体,主键ID类型>,接口名称自定义,跟Jpa类似。

import cn.ityao.es.entity.Person;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

/**
 * springboot-es >>> 【cn.ityao.es.service】
 *
 * @author: tongyao
 * @since: 2023-05-16 15:16
 */
public interface IPersonService extends ElasticsearchRepository<Person,String> {
    
    

    //根据name查询
    List<Person> findByName(String name);

    //根据name和info查询
    List<Person> findByNameAndInfo(String name, String info);
}

Controller

import cn.ityao.es.entity.Person;
import cn.ityao.es.service.IPersonService;
import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * springboot-es >>> 【cn.ityao.es.controller】
 *
 * @author: tongyao
 * @since: 2023-05-16 15:17
 */
@RestController
public class PersonController {
    
    

    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;
    @Autowired
    private IPersonService iPersonService;

    private String[] names = {
    
    "诸葛亮", "曹操", "李白", "韩信", "赵云", "小乔", "狄仁杰", "李四", "诸小明", "王五"};
    private String[] infos = {
    
    "我来自中国的一个小乡村,地处湖南省", "我来自中国的一个大城市,名叫上海,人们称作魔都"
            , "我来自杭州,这是一个浪漫的城市"};

    /**
     * 保存数据
     *
     * @return
     */
    @GetMapping("saveUser")
    public Object saveUser() {
    
    
        //添加索引mapping索引会自动创建但mapping自只用默认的这会导致分词器不生效 所以这里我们手动导入mapping
        Random random = new Random();
        List<Person> users = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
    
    
            Person person = new Person();
            person.setId(i+"");
            person.setName(names[random.nextInt(9)]);
            person.setAge(random.nextInt(40) + i);
            person.setInfo(infos[random.nextInt(2)]);
            users.add(person);
        }
        Iterable<Person> users1 = iPersonService.saveAll(users);

        return users1;
    }

    /**
     * 通过id查询数据
     *
     * @return
     */
    @GetMapping("getDataById")
    public Object getDataById(@RequestParam(value = "id") String id) {
    
    
        return iPersonService.findById(id);
    }

    /**
     * 分页查询
     *
     * @return
     */
    @GetMapping("getAllDataByPage")
    public Object getAllDataByPage() {
    
    
        //本该传入page和size,这里为了方便就直接写死了
        //表示通过Id正序排序
        Pageable page = PageRequest.of(0, 3, Sort.Direction.ASC, "id");
        Page<Person> all = iPersonService.findAll(page);
        return all.getContent();
    }

    /**
     * 根据名字查询
     *
     * @param name
     * @return
     */
    @GetMapping("getDataByName")
    public Object getDataByName(@RequestParam(value = "name") String name) {
    
    
        return iPersonService.findByName(name);
    }

    /**
     * 通过名字和Info取交集查询
     *
     * @param name
     * @param info
     * @return
     */
    @GetMapping("getDataByNameAndInfo")
    public Object getDataByNameAndInfo(String name, String info) {
    
    
        //这里是查询两个字段取交集,即代表两个条件需要同时满足
        return iPersonService.findByNameAndInfo(name, info);
    }

    /**
     * 分词高亮查询
     *
     * @param value
     * @return
     */
    @GetMapping("getHightByUser")
    public Object getHightByUser(@RequestParam(value = "value") String value) {
    
    
        //根据一个值查询多个字段  并高亮显示  这里的查询是取并集,即多个字段只需要有一个字段满足即可

        BoolQueryBuilder boolQueryBuilder= QueryBuilders.boolQuery()
                .should(QueryBuilders.matchQuery("name",value))
                .should(QueryBuilders.matchQuery("info",value));

        NativeSearchQuery nativeSearchQuery=new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder)
                .withHighlightFields(new HighlightBuilder.Field("name"),new HighlightBuilder.Field("info"))
                .withHighlightBuilder(new HighlightBuilder().preTags("<span style='color:red'>").postTags("</span>"))
                // 高亮分页,注释就是默认全部
                /*.withPageable(PageRequest.of(0,3))*/
                .build();
        AggregatedPage<Person> aggregatedPage = elasticsearchTemplate.queryForPage(nativeSearchQuery, Person.class, new SearchResultMapper() {
    
    
            @Override
            public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
    
    
                ArrayList<Person> personArrayList = new ArrayList<Person>();
                SearchHits hits = response.getHits();
                for (SearchHit searchHit : hits) {
    
    
                    if (hits.getHits().length <= 0) {
    
    
                        return null;
                    }
                    Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();
                    String id = sourceAsMap.get("id").toString();
                    String name = sourceAsMap.get("name").toString();
                    String info = sourceAsMap.get("info").toString();

                    Person person = new Person();


                    HighlightField contentHighlightField = searchHit.getHighlightFields().get("info");
                    if(contentHighlightField==null){
    
    
                        person.setInfo(info);
                    }else{
    
    
                        String highLightMessage = searchHit.getHighlightFields().get("info").fragments()[0].toString();
                        /*articleInfo.setInfo(StringUtil.stripHtml(highLightMessage).replaceAll("_",""));*/
                        person.setInfo(highLightMessage.replaceAll("_",""));
                    }


                    HighlightField nameHighlightField =searchHit.getHighlightFields().get("name");
                    if(nameHighlightField==null){
    
    
                        person.setName(name);
                    }else{
    
    
                        person.setName(searchHit.getHighlightFields().get("name").fragments()[0].toString());
                    }
                    person.setId(id);

                    personArrayList.add(person);
                }
                if (personArrayList.size() > 0) {
    
    
                    return new AggregatedPageImpl<T>((List<T>) personArrayList);
                }
                return null;

            }

            @Override
            public <T> T mapSearchHit(SearchHit searchHit, Class<T> aClass) {
    
    
                return null;
            }
        });
        List<Person> list = aggregatedPage.getContent();
        // 总数据量
        long total = aggregatedPage.getTotalElements();
        // 总页数
        long totalPage = aggregatedPage.getTotalPages();
        return list;
    }

}

测试

先调用加入数据接口。
http://localhost:9200/saveUser

在这里插入图片描述
查询数据接口

http://localhost:9990/getHightByUser?value=中国

在这里插入图片描述
参考文章:https://blog.csdn.net/zhiyikeji/article/details/128908596

猜你喜欢

转载自blog.csdn.net/u014641168/article/details/130721363
今日推荐