Java操作Elasticsearch的实用指南

海哥  金牌会员 | 2024-9-12 00:37:14 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 534|帖子 534|积分 1602

一、创建索引

在ElasticSearch中索引相当于mysql中的表,mapping相当于表布局,所以第一步我们要先创建索引。


  • 假设我们有一张文章表的数据必要同步到ElasticSearch,首先必要根据数据库表创建ES的索引布局。
  1. -- 文章表
  2. create table if not exists post
  3. (
  4.     id         bigint auto_increment comment 'id' primary key,
  5.     title      varchar(512)                       null comment '标题',
  6.     content    text                               null comment '内容',
  7.     tags       varchar(1024)                      null comment '标签列表(json 数组)',
  8.     thumbNum   int      default 0                 not null comment '点赞数',
  9.     favourNum  int      default 0                 not null comment '收藏数',
  10.     userId     bigint                             not null comment '创建用户 id',
  11.     createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间',
  12.     updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
  13.     isDelete   tinyint  default 0                 not null comment '是否删除',
  14.     index idx_userId (userId)
  15. ) comment '帖子' collate = utf8mb4_unicode_ci;
复制代码
ElasticSearch的索引布局:


  • aliases:别名(为了方便后续数据迁徙)
  • 字段范例是text,这个字段可以被分词,可模糊查询;字段范例是keyword,只能完全匹配,准确查询。
  • analyzer(存储时生效的分词器):用ik_max_word,拆的更碎、索引更多,更有大概被搜出来
  • search analyzer (查询时生效的分词器):用ik_smart,更偏向于用户想要搜的分词。
  1. PUT post
  2. {
  3.   "aliases": {
  4.     "post": {}
  5.   },
  6.   "mappings": {
  7.     "properties": {
  8.       "title": {
  9.         "type": "text",
  10.         "analyzer": "ik_max_word",
  11.         "search_analyzer": "ik_smart",
  12.         "fields": {
  13.           "keyword": {
  14.             "type": "keyword",
  15.             "ignore_above": 256
  16.           }
  17.         }
  18.       },
  19.       "content": {
  20.         "type": "text",
  21.         "analyzer": "ik_max_word",
  22.         "search_analyzer": "ik_smart",
  23.         "fields": {
  24.           "keyword": {
  25.             "type": "keyword",
  26.             "ignore_above": 256
  27.           }
  28.         }
  29.       },
  30.       "tags": {
  31.         "type": "keyword"
  32.       },
  33.       "userId": {
  34.         "type": "keyword"
  35.       },
  36.       "createTime": {
  37.         "type": "date"
  38.       },
  39.       "updateTime": {
  40.         "type": "date"
  41.       },
  42.       "isDelete": {
  43.         "type": "keyword"
  44.       }
  45.     }
  46.   }
  47. }
复制代码

二、增编削查

使用java客户端进行增编削查,第一步导入依赖。
  1. <!-- elasticsearch-->
  2.         <dependency>
  3.             <groupId>org.springframework.boot</groupId>
  4.             <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  5.         </dependency>
复制代码


  • 第一种方式: ElasticsearchRepository<ostEsDTO,Long>,默认提供了简朴的增编削查,多用于可预期的、相对没那么复杂的查询、自定义查询。

  1.    @Test
  2.     void testSelect() {
  3.         System.out.println(postEsDao.count());
  4.         Page<PostEsDTO> PostPage = postEsDao.findAll(
  5.                 PageRequest.of(0, 5, Sort.by("createTime")));
  6.         List<PostEsDTO> postList = PostPage.getContent();
  7.         System.out.println(postList);
  8.     }
  9.     @Test
  10.     void testAdd() {
  11.         PostEsDTO postEsDTO = new PostEsDTO();
  12.         postEsDTO.setId(1L);
  13.         postEsDTO.setTitle("我是章三");
  14.         postEsDTO.setContent("张三学习java,学习使我快乐!");
  15.         postEsDTO.setTags(Arrays.asList("java", "python"));
  16.         postEsDTO.setUserId(1L);
  17.         postEsDTO.setCreateTime(new Date());
  18.         postEsDTO.setUpdateTime(new Date());
  19.         postEsDTO.setIsDelete(0);
  20.         postEsDao.save(postEsDTO);
  21.         System.out.println(postEsDTO.getId());
  22.     }
  23.     @Test
  24.     void testFindById() {
  25.         Optional<PostEsDTO> postEsDTO = postEsDao.findById(1L);
  26.         System.out.println(postEsDTO);
  27.     }
  28.     @Test
  29.     void testCount() {
  30.         System.out.println(postEsDao.count());
  31.     }
  32.     @Test
  33.     void testFindByCategory() {
  34.         List<PostEsDTO> postEsDaoTestList = postEsDao.findByUserId(1L);
  35.         System.out.println(postEsDaoTestList);
  36.     }
复制代码
ES 中,_开头的字段表示体系默认字段,比如 _id,如果体系不指定,会主动天生。但是不会在surce 字段中增补 id 的值,所以发起大家手动指定。
支持根据方法名主动天生方法,比如:
  1. ListcPostEsDTO> findByTitle(String title);
复制代码


  • 第二种方式: Spring 默认给我们提供的提作 es 的客户端对象 ElasticsearchRestTemplate,也提供了增制改查,它的增编削查更机动,实用于更复杂的操作。
    ES的搜索条件:
  1. GET /_search
  2. {
  3.   "query": {
  4.     "bool": {   组合条件
  5.       "must": [   必须都满足
  6.         { "match": { "title":   "Search"  }},   模糊查询   
  7.         { "match": { "content": "Elasticsearch" }}
  8.       ],
  9.       "filter": [
  10.         { "term":  { "status": "published" }},  精确查询
  11.         { "range": { "publish_date": { "gte": "2015-01-01" }}}  范围查询
  12.       ],
  13.       "should" : [
  14.         { "term" : { "tags" : "env1" } },
  15.         { "term" : { "tags" : "deployed" } }
  16.       ],
  17.       "minimum_should_match" : 1,   包含匹配,最少匹配1条
  18.       "boost" : 1.0
  19.     }
  20.   }
  21. }
复制代码
对于复杂的查询,发起使用第二种方式。
  1. //依赖注入
  2. @Resource
  3.     private ElasticsearchRestTemplate elasticsearchRestTemplate;
复制代码
三个步调:
1、取参数
2、把参数组合为ES支持的搜索条件
3、从返回值中取效果
  1.        Long id = postQueryRequest.getId();
  2.         Long notId = postQueryRequest.getNotId();
  3.         String searchText = postQueryRequest.getSearchText();
  4.         String title = postQueryRequest.getTitle();
  5.         String content = postQueryRequest.getContent();
  6.         List<String> tagList = postQueryRequest.getTags();
  7.         List<String> orTagList = postQueryRequest.getOrTags();
  8.         Long userId = postQueryRequest.getUserId();
  9.         // es 起始页为 0
  10.         long current = postQueryRequest.getCurrent() - 1;
  11.         long pageSize = postQueryRequest.getPageSize();
  12.         String sortField = postQueryRequest.getSortField();
  13.         String sortOrder = postQueryRequest.getSortOrder();
  14.         BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  15.         // 过滤
  16.         boolQueryBuilder.filter(QueryBuilders.termQuery("isDelete", 0));
  17.         if (id != null) {
  18.             boolQueryBuilder.filter(QueryBuilders.termQuery("id", id));
  19.         }
  20.         if (notId != null) {
  21.             boolQueryBuilder.mustNot(QueryBuilders.termQuery("id", notId));
  22.         }
  23.         if (userId != null) {
  24.             boolQueryBuilder.filter(QueryBuilders.termQuery("userId", userId));
  25.         }
  26.         // 必须包含所有标签
  27.         if (CollectionUtils.isNotEmpty(tagList)) {
  28.             for (String tag : tagList) {
  29.                 boolQueryBuilder.filter(QueryBuilders.termQuery("tags", tag));
  30.             }
  31.         }
  32.         // 包含任何一个标签即可
  33.         if (CollectionUtils.isNotEmpty(orTagList)) {
  34.             BoolQueryBuilder orTagBoolQueryBuilder = QueryBuilders.boolQuery();
  35.             for (String tag : orTagList) {
  36.                 orTagBoolQueryBuilder.should(QueryBuilders.termQuery("tags", tag));
  37.             }
  38.             orTagBoolQueryBuilder.minimumShouldMatch(1);
  39.             boolQueryBuilder.filter(orTagBoolQueryBuilder);
  40.         }
  41.         // 按关键词检索
  42.         if (StringUtils.isNotBlank(searchText)) {
  43.             boolQueryBuilder.should(QueryBuilders.matchQuery("title", searchText));
  44.           //  boolQueryBuilder.should(QueryBuilders.matchQuery("description", searchText));
  45.             boolQueryBuilder.should(QueryBuilders.matchQuery("content", searchText));
  46.             boolQueryBuilder.minimumShouldMatch(1);
  47.         }
  48.         // 按标题检索
  49.         if (StringUtils.isNotBlank(title)) {
  50.             boolQueryBuilder.should(QueryBuilders.matchQuery("title", title));
  51.             boolQueryBuilder.minimumShouldMatch(1);
  52.         }
  53.         // 按内容检索
  54.         if (StringUtils.isNotBlank(content)) {
  55.             boolQueryBuilder.should(QueryBuilders.matchQuery("content", content));
  56.             boolQueryBuilder.minimumShouldMatch(1);
  57.         }
  58.         // 排序
  59.         SortBuilder<?> sortBuilder = SortBuilders.scoreSort();
  60.         if (StringUtils.isNotBlank(sortField)) {
  61.             sortBuilder = SortBuilders.fieldSort(sortField);
  62.             sortBuilder.order(CommonConstant.SORT_ORDER_ASC.equals(sortOrder) ? SortOrder.ASC : SortOrder.DESC);
  63.         }
  64.         // 分页
  65.         PageRequest pageRequest = PageRequest.of((int) current, (int) pageSize);
  66.         // 构造查询
  67.         NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder)
  68.                 .withPageable(pageRequest).withSorts(sortBuilder).build();
  69.         SearchHits<PostEsDTO> searchHits = elasticsearchRestTemplate.search(searchQuery, PostEsDTO.class);
复制代码
后记

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

海哥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表