ElasticSearch系列四 CURD

Posted dgwblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ElasticSearch系列四 CURD相关的知识,希望对你有一定的参考价值。

1: ES 类似JPA操作

1.1 编写实体类

1.2 编写映射文件 xxx.json

1.3编写repository继承 ElasticSearchrepository

1.4 编写admin 的CRUD

2: 使用ElasticSearchtemplate 对索引操作

2.1 对索引的各类操作

3: 高级查询

配置application

##es 单个ES地址 #spring.data.elasticsearch.cluster-nodes= ## 设置ES多个地址 
spring.data.elasticsearch.client.reactive.endpoints=[http://localhost:9200] ## 
开启repositories spring.data.elasticsearch.repositories.enabled=true 
#spring.data.elasticsearch.client.reactive.connection-timeout= 
#spring.data.elasticsearch.client.reactive.password= 
#spring.data.elasticsearch.client.reactive.socket-timeout= 
#spring.data.elasticsearch.client.reactive.username= ##es  单个ES地址
#spring.data.elasticsearch.cluster-nodes=
##  设置ES多个地址
spring.data.elasticsearch.client.reactive.endpoints=[http://localhost:9200]
## 开启repositories
spring.data.elasticsearch.repositories.enabled=true
#spring.data.elasticsearch.client.reactive.connection-timeout=
#spring.data.elasticsearch.client.reactive.password=
#spring.data.elasticsearch.client.reactive.socket-timeout=
#spring.data.elasticsearch.client.reactive.username=

pom依赖

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

1: ES 类似JPA操作

1.1 编写实体类

// indexName: 索引名称  type: 执行数据库类型的表
@Document(indexName = "esadmin",type = "admin")
@Mapping(mappingPath = "admin_es.json") //指向映射文件
public class Admin {

    @Id
    private Long id;
    private String username;
    private String password;
    private String loveThings;
    // getter setter 方法

1.2 编写映射文件 xxx.json

{
  "properties": {
    "id": {
      "type": "long"
    },
    "username": {
      "type": "string",
      "index":    "not_analyzed"
    },
    "password": {
      "type": "string",
      "index":    "not_analyzed"
    },
    "loveThings": {
      "type": "text",
      "analyzer": "ik_max_word",
      "search_analyzer": "ik_max_word"
    }
  }
}

1.3编写repository继承 ElasticSearchrepository

@Repository public interface AdminRepository extends 
ElasticsearchRepository&lt;Admin,Long&gt; { }

1.4 编写admin 的CRUD

@RestController
public class AdminController {

    @Autowired
    private AdminRepository adminRepository;

    // http://localhost:8080/saveOrUpdate

    /**
     *  send data
     * {
     *     "username":"dgw3",
     *     "password":"root",
     *     "loveThings":"postman(二):使用postman发送get or post请"
     * }
     */
    @PostMapping("saveOrUpdate")
    public String saveOrUpdate(@RequestBody Admin admin){
        if(admin.getId()==null){
            admin.setId(System.currentTimeMillis());
        }
        adminRepository.save(admin);
        return "保存成功";
    }
    //http://localhost:8080/delete?id=1582946734759
    @GetMapping("delete")
    public String delete(Long id){
        try {
            adminRepository.deleteById(id);
        } catch (Exception e) {
            e.printStackTrace();
            return "删除失败";
        }
        return "删除成功";
    }
    //http://localhost:8080/findById?id=1582946734759
    @GetMapping("findById")
    public Admin findById(long id){
        Optional<Admin> admin = adminRepository.findById(id);
        if(admin.isPresent()){
            return admin.get();
        }else{
            return null;
        }
    }
    //http://localhost:8080/findAll
    @GetMapping("findAll")
    public Iterable<Admin> findAll(){
            return adminRepository.findAll();
    }
}

2: 使用ElasticSearchtemplate 对索引操作

2.1 对索引的各类操作

@RestController
public class ElasticOperationControler {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @GetMapping("createIndex")
    public boolean createIndex(String indexName){
        return elasticsearchTemplate.createIndex(indexName);
    }

    @GetMapping("deleteIndex")
    public boolean deleteIndex(String indexName){
        return elasticsearchTemplate.deleteIndex(indexName);
    }

    @GetMapping("indexIsExist")
    public boolean indexIsExist(String indexName){
        return elasticsearchTemplate.indexExists(indexName);
    }

    @GetMapping("typeIsExist")
    public boolean typeIsExist(String indexName,String type){
        return elasticsearchTemplate.typeExists(indexName,type);
    }

    @GetMapping("getMapping")
    public Map getMapping(String indexName, String type){
        return elasticsearchTemplate.getMapping(indexName,type);
    }

    @GetMapping("getSetting")
    public Map getSetting(String indexName){
        return elasticsearchTemplate.getSetting(indexName);
    }
}

3: 高级查询

查询步骤:

  • QueryBuilders 构建查询关键词
  • SortBuilders 构建对关键字的排序
  • NativeSearchQueryBuilder 对前两个条件进行封装,
  • Repository : 进行查询
@RestController
public class SearchController {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    private ArticleRepository articleRepository;

    //1.不分词查询:查询articleContent带有你好 或者 articleName带有你好的文章列表,并且按照readCount倒叙排序
    //http://localhost:8080/query1?keyword=你好
    @GetMapping("query1")
    public List<Article> query1(String keyword) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        BoolQueryBuilder articleContent = boolQuery.should(QueryBuilders.termQuery("articleContent", keyword));
        BoolQueryBuilder articleName = boolQuery.should(QueryBuilders.termQuery("articleName", keyword));

        FieldSortBuilder order = SortBuilders.fieldSort("readCount").order(SortOrder.DESC);

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();

        nativeSearchQueryBuilder.withQuery(articleContent);
        nativeSearchQueryBuilder.withQuery(articleName);
        nativeSearchQueryBuilder.withSort(order);

        NativeSearchQuery searchQuery = nativeSearchQueryBuilder.build();

        Page<Article> articles = articleRepository.search(searchQuery);
        if (articles != null) {
            return articles.getContent();
        } else {
            return null;
        }
    }
    //2.不分词查询:查询articleContent带有我们 或者 你好 并且authorAge在20岁以下的文章列表,并且按照readCount倒叙排序
    //http://localhost:8080/query11?keyword=你好,我们
    @GetMapping("query2")
    public List<Article> query2(String... keyword) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termsQuery("articleContent", keyword));
        boolQueryBuilder.must(QueryBuilders.rangeQuery("authorAge").lt(20));
        FieldSortBuilder fieldSortBuilder = SortBuilders.fieldSort("readCount").order(SortOrder.DESC);
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        nativeSearchQueryBuilder.withSort(fieldSortBuilder);
        NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder.build();
        Page<Article> page = articleRepository.search(nativeSearchQuery);
        if (page != null) {
            return page.getContent();
        } else {
            return null;
        }
    }

    //3.分词查询:经过分词,查询articleContent带有你好节日一词分词后的文章列表,并且按照authorAge倒叙排序
    //http://localhost:8080/query12?keyword=你好节日
    @GetMapping("query3")
    public List<Article> query3(String keyword) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.should(QueryBuilders.matchQuery("articleContent", keyword));
        FieldSortBuilder fieldSortBuilder = SortBuilders.fieldSort("authorAge").order(SortOrder.DESC);
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        nativeSearchQueryBuilder.withSort(fieldSortBuilder);
        NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder.build();
        Page<Article> page = articleRepository.search(nativeSearchQuery);
        if (page != null) {
            return page.getContent();
        } else {
            return null;
        }
    }

    //4.分页分词查询:经过分词,查询articleContent带有你好节日一词分词后的文章列表,并且按照authorAge倒叙排序
    //http://localhost:8080/query13?keyword=你好节日&pageNum=1&pageSize=5
    @GetMapping("query4")
    public Page<Article> query4(String keyword, Integer pageNum, Integer pageSize) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.should(QueryBuilders.matchQuery("articleContent", keyword));
        FieldSortBuilder fieldSortBuilder = SortBuilders.fieldSort("authorAge").order(SortOrder.DESC);
        PageRequest pageRequest = new PageRequest(pageNum, pageSize);
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        nativeSearchQueryBuilder.withSort(fieldSortBuilder);
        nativeSearchQueryBuilder.withPageable(pageRequest);
        NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder.build();
        Page<Article> page = articleRepository.search(nativeSearchQuery);
        if (page != null) {
            return page;
        } else {
            return null;
        }
    }

    //5.分页分词查询:经过分词,查询articleContent带有你好节日一词分词后的文章列表,并且按照authorAge倒叙排序,并且对匹配到的词语设置为高亮
    //http://localhost:8080/query14?keyword=你好节日&pageNum=1&pageSize=5&fieldNames=articleContent,articleName
    @GetMapping("query5")
    public Map<String, Object> query5(String keyword, Integer pageNum, Integer pageSize, String... fieldNames) {

        //定义返回的map
        Map<String, Object> returnMap = new HashMap<String,Object>();

        // 不使用默认的分词器  直接操控索引
        //构建请求构建器,设置查询索引
        SearchRequestBuilder builder = elasticsearchTemplate.getClient().prepareSearch("testes");

        //构建查询构建器,设置分词器(如果没设置使用默认)
        QueryBuilder matchQuery = QueryBuilders.multiMatchQuery(keyword, fieldNames).analyzer("ik_max_word");

        //构建高亮构建器
        HighlightBuilder highlightBuilder = new HighlightBuilder().field("*").requireFieldMatch(false);
        highlightBuilder.preTags("<span style="color:red">");
        highlightBuilder.postTags("</span>");

        //将高亮构建器,查询构建器,分页参数设置到请求构建器内
        builder.highlighter(highlightBuilder);
        builder.setQuery(matchQuery);
        builder.setFrom((pageNum - 1) * pageSize);
        builder.setSize(pageNum * pageSize);
        builder.setSize(pageSize);

        //执行搜索,返回搜索响应信息
        SearchResponse searchResponse = builder.get();
        SearchHits searchHits = searchResponse.getHits();

        //总命中数
        long total = searchHits.getTotalHits();
        returnMap.put("count", total);

        //将高亮字段封装到返回map
        SearchHit[] hits = searchHits.getHits();
        List<Map<String,Object>> list = new ArrayList<>();
        Map<String,Object> map;
        for(SearchHit searchHit : hits){
            map = new HashMap<>();
            map.put("data",searchHit.getSourceAsMap());
            Map<String,Object> hitMap = new HashMap<>();
            searchHit.getHighlightFields().forEach((k,v) -> {
                String hight = "";
                for(Text text : v.getFragments()){
                    hight += text.string();
                }
                hitMap.put(v.getName(),hight);
            });
            map.put("highlight",hitMap);
            list.add(map);
        }
        returnMap.put("dataList", list);
        return returnMap;
    }

以上是关于ElasticSearch系列四 CURD的主要内容,如果未能解决你的问题,请参考以下文章

四.全文检索ElasticSearch经典入门-ElasticSearch DSL查询

Spring Boot系列——Restful CURD注意事项

全文检索-Elasticsearch CURD与DSL

elasticsearch中document的CURD

ElasticSearch学习之——基本的文档CURD

ElasticSearch实战系列四: ElasticSearch理论知识介绍