一、创建索引
在ElasticSearch中索引相当于mysql中的表,mapping相当于表布局,所以第一步我们要先创建索引。
- 假设我们有一张文章表的数据必要同步到ElasticSearch,首先必要根据数据库表创建ES的索引布局。
- -- 文章表
- create table if not exists post
- (
- id bigint auto_increment comment 'id' primary key,
- title varchar(512) null comment '标题',
- content text null comment '内容',
- tags varchar(1024) null comment '标签列表(json 数组)',
- thumbNum int default 0 not null comment '点赞数',
- favourNum int default 0 not null comment '收藏数',
- userId bigint not null comment '创建用户 id',
- createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间',
- updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间',
- isDelete tinyint default 0 not null comment '是否删除',
- index idx_userId (userId)
- ) comment '帖子' collate = utf8mb4_unicode_ci;
复制代码 ElasticSearch的索引布局:
- aliases:别名(为了方便后续数据迁徙)
- 字段范例是text,这个字段可以被分词,可模糊查询;字段范例是keyword,只能完全匹配,准确查询。
- analyzer(存储时生效的分词器):用ik_max_word,拆的更碎、索引更多,更有大概被搜出来
- search analyzer (查询时生效的分词器):用ik_smart,更偏向于用户想要搜的分词。
- PUT post
- {
- "aliases": {
- "post": {}
- },
- "mappings": {
- "properties": {
- "title": {
- "type": "text",
- "analyzer": "ik_max_word",
- "search_analyzer": "ik_smart",
- "fields": {
- "keyword": {
- "type": "keyword",
- "ignore_above": 256
- }
- }
- },
- "content": {
- "type": "text",
- "analyzer": "ik_max_word",
- "search_analyzer": "ik_smart",
- "fields": {
- "keyword": {
- "type": "keyword",
- "ignore_above": 256
- }
- }
- },
- "tags": {
- "type": "keyword"
- },
- "userId": {
- "type": "keyword"
- },
- "createTime": {
- "type": "date"
- },
- "updateTime": {
- "type": "date"
- },
- "isDelete": {
- "type": "keyword"
- }
- }
- }
- }
复制代码
二、增编削查
使用java客户端进行增编削查,第一步导入依赖。
- <!-- elasticsearch-->
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
- </dependency>
复制代码
- 第一种方式: ElasticsearchRepository<ostEsDTO,Long>,默认提供了简朴的增编削查,多用于可预期的、相对没那么复杂的查询、自定义查询。
- @Test
- void testSelect() {
- System.out.println(postEsDao.count());
- Page<PostEsDTO> PostPage = postEsDao.findAll(
- PageRequest.of(0, 5, Sort.by("createTime")));
- List<PostEsDTO> postList = PostPage.getContent();
- System.out.println(postList);
- }
- @Test
- void testAdd() {
- PostEsDTO postEsDTO = new PostEsDTO();
- postEsDTO.setId(1L);
- postEsDTO.setTitle("我是章三");
- postEsDTO.setContent("张三学习java,学习使我快乐!");
- postEsDTO.setTags(Arrays.asList("java", "python"));
- postEsDTO.setUserId(1L);
- postEsDTO.setCreateTime(new Date());
- postEsDTO.setUpdateTime(new Date());
- postEsDTO.setIsDelete(0);
- postEsDao.save(postEsDTO);
- System.out.println(postEsDTO.getId());
- }
- @Test
- void testFindById() {
- Optional<PostEsDTO> postEsDTO = postEsDao.findById(1L);
- System.out.println(postEsDTO);
- }
- @Test
- void testCount() {
- System.out.println(postEsDao.count());
- }
- @Test
- void testFindByCategory() {
- List<PostEsDTO> postEsDaoTestList = postEsDao.findByUserId(1L);
- System.out.println(postEsDaoTestList);
- }
复制代码 ES 中,_开头的字段表示体系默认字段,比如 _id,如果体系不指定,会主动天生。但是不会在surce 字段中增补 id 的值,所以发起大家手动指定。
支持根据方法名主动天生方法,比如:
- ListcPostEsDTO> findByTitle(String title);
复制代码
- 第二种方式: Spring 默认给我们提供的提作 es 的客户端对象 ElasticsearchRestTemplate,也提供了增制改查,它的增编削查更机动,实用于更复杂的操作。
ES的搜索条件:
- GET /_search
- {
- "query": {
- "bool": { 组合条件
- "must": [ 必须都满足
- { "match": { "title": "Search" }}, 模糊查询
- { "match": { "content": "Elasticsearch" }}
- ],
- "filter": [
- { "term": { "status": "published" }}, 精确查询
- { "range": { "publish_date": { "gte": "2015-01-01" }}} 范围查询
- ],
- "should" : [
- { "term" : { "tags" : "env1" } },
- { "term" : { "tags" : "deployed" } }
- ],
- "minimum_should_match" : 1, 包含匹配,最少匹配1条
- "boost" : 1.0
- }
- }
- }
复制代码 对于复杂的查询,发起使用第二种方式。
- //依赖注入
- @Resource
- private ElasticsearchRestTemplate elasticsearchRestTemplate;
复制代码 三个步调:
1、取参数
2、把参数组合为ES支持的搜索条件
3、从返回值中取效果
- Long id = postQueryRequest.getId();
- Long notId = postQueryRequest.getNotId();
- String searchText = postQueryRequest.getSearchText();
- String title = postQueryRequest.getTitle();
- String content = postQueryRequest.getContent();
- List<String> tagList = postQueryRequest.getTags();
- List<String> orTagList = postQueryRequest.getOrTags();
- Long userId = postQueryRequest.getUserId();
- // es 起始页为 0
- long current = postQueryRequest.getCurrent() - 1;
- long pageSize = postQueryRequest.getPageSize();
- String sortField = postQueryRequest.getSortField();
- String sortOrder = postQueryRequest.getSortOrder();
- BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
- // 过滤
- boolQueryBuilder.filter(QueryBuilders.termQuery("isDelete", 0));
- if (id != null) {
- boolQueryBuilder.filter(QueryBuilders.termQuery("id", id));
- }
- if (notId != null) {
- boolQueryBuilder.mustNot(QueryBuilders.termQuery("id", notId));
- }
- if (userId != null) {
- boolQueryBuilder.filter(QueryBuilders.termQuery("userId", userId));
- }
- // 必须包含所有标签
- if (CollectionUtils.isNotEmpty(tagList)) {
- for (String tag : tagList) {
- boolQueryBuilder.filter(QueryBuilders.termQuery("tags", tag));
- }
- }
- // 包含任何一个标签即可
- if (CollectionUtils.isNotEmpty(orTagList)) {
- BoolQueryBuilder orTagBoolQueryBuilder = QueryBuilders.boolQuery();
- for (String tag : orTagList) {
- orTagBoolQueryBuilder.should(QueryBuilders.termQuery("tags", tag));
- }
- orTagBoolQueryBuilder.minimumShouldMatch(1);
- boolQueryBuilder.filter(orTagBoolQueryBuilder);
- }
- // 按关键词检索
- if (StringUtils.isNotBlank(searchText)) {
- boolQueryBuilder.should(QueryBuilders.matchQuery("title", searchText));
- // boolQueryBuilder.should(QueryBuilders.matchQuery("description", searchText));
- boolQueryBuilder.should(QueryBuilders.matchQuery("content", searchText));
- boolQueryBuilder.minimumShouldMatch(1);
- }
- // 按标题检索
- if (StringUtils.isNotBlank(title)) {
- boolQueryBuilder.should(QueryBuilders.matchQuery("title", title));
- boolQueryBuilder.minimumShouldMatch(1);
- }
- // 按内容检索
- if (StringUtils.isNotBlank(content)) {
- boolQueryBuilder.should(QueryBuilders.matchQuery("content", content));
- boolQueryBuilder.minimumShouldMatch(1);
- }
- // 排序
- SortBuilder<?> sortBuilder = SortBuilders.scoreSort();
- if (StringUtils.isNotBlank(sortField)) {
- sortBuilder = SortBuilders.fieldSort(sortField);
- sortBuilder.order(CommonConstant.SORT_ORDER_ASC.equals(sortOrder) ? SortOrder.ASC : SortOrder.DESC);
- }
- // 分页
- PageRequest pageRequest = PageRequest.of((int) current, (int) pageSize);
- // 构造查询
- NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder)
- .withPageable(pageRequest).withSorts(sortBuilder).build();
- SearchHits<PostEsDTO> searchHits = elasticsearchRestTemplate.search(searchQuery, PostEsDTO.class);
复制代码 后记
|