ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Elasticsearch7学习笔记(实战)

2021-04-12 09:05:06  阅读:189  来源: 互联网

标签:实战 String pinyin private Elasticsearch7 笔记 stationName new import


在SpringBoot中集成Elasticsearch的使用示例,带你快速上手使用Elasticsearch。

添加如下maven依赖:

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

注意在这里引入es的jar包版本要比elasticsearch版本相等或大于(最好相等),否则可能会出现一些奇奇怪怪的问题。

在application.yml配置文件中添加elasticsearch的配置(可以配置多个)

spring:
  elasticsearch:
    rest:
      uris: http://192.168.111.55:9200

如果没有什么特殊的配置的话,直接使用springboot自动配置的即可;自定义配置时,可以参考springboot的中配置;

spring文档:https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html

示例:查询以某个字符开头的数据

这里我们实现类似12306查询站点时的智能提示功能,即输入北京会智能显示北京开头的站点。下面的示例使用的是webflux

12306火车站点信息数据拉取

站点数据:https://www.12306.cn/index/script/core/common/station_name_v10095.js

数据解析程序如下:

private static final String STATION_NAME_URL = "https://www.12306.cn/index/script/core/common/station_name_v10095.js";

 /**
 * 导入站点数据
 */
public Mono<String> importTrainStationName() {
    return WebClient.create(STATION_NAME_URL).get().retrieve()
            .onStatus(HttpStatus::is4xxClientError, clientResponse-> Mono.error(new BizException("数据拉取失败")))
            .bodyToMono(String.class)
            .flatMap(body->{
                List<TrainStationName> list = extractStationName(body);
                return Mono.just(batchInsert(list));
            });
}

 /**
 * 提取数据
 */
private List<TrainStationName> extractStationName(String str){
    String[] arr = str.split("\\|");
    List<TrainStationName> list = new ArrayList<>();
    for(int i=1; i<arr.length; i++){
        TrainStationName stationName = new TrainStationName();
        stationName.setCnName(arr[i++]);
        stationName.setCode(arr[i++]);
        stationName.setPinyin(arr[i++]);
        stationName.setPinyinShort(arr[i++]);
        list.add(stationName);
    }
    return list;
}

 /**
 * 导入数据到库中
 */
private String batchInsert(List<TrainStationName> list){
    int add = 0;
    int totalPull = list.size();
    for(TrainStationName stationName:list){
        LambdaQueryWrapper<TrainStationName> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TrainStationName::getCnName, stationName.getCnName());
        TrainStationName stationNameDb = trainStationNameMapper.selectOne(queryWrapper);
        if(stationNameDb==null){
            add++;
            trainStationNameMapper.insert(stationName);
            stationNameDb = stationName;
        }

        if(stationNameDb.getId()!=null){
            boolean exists = trainStationNameRepository.existsById(stationNameDb.getId());
            if(!exists){
                trainStationNameRepository.save(TrainStationNameDTO.cloneTrainStationName(stationNameDb));
            }
        }
    }
    return String.format("共计拉取:%d条数据,新增:%d条数据", totalPull, add);
}

站点数据pojo

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

@Data
@TableName("train_station_name")
public class TrainStationName implements Serializable {

    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    /**
     * 三字码
     */
    @TableField("code")
    private String code;

    /**
     * 拼音
     */
    @TableField("pinyin")
    private String pinyin;

    /**
     * 拼音简写
     */
    @TableField("pinyin_short")
    private String pinyinShort;

    /**
     * 中文名称
     */
    @TableField("cn_name")
    private String cnName;

}

es中的实体类映射

import lombok.Data;
import org.springframework.beans.BeanUtils;
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;
import top.vchar.train.entity.TrainStationName;

import java.io.Serializable;

@Data
@Document(indexName = "train_station_name")
public class TrainStationNameDTO implements Serializable {

    @Id
    private Long id;

    /**
     * 三字码
     */
    @Field(type = FieldType.Keyword)
    private String code;

    /**
     * 拼音
     */
    @Field(type = FieldType.Keyword)
    private String pinyin;

    /**
     * 拼音简写
     */
    @Field(type = FieldType.Keyword)
    private String pinyinShort;

    /**
     * 中文名称
     */
    @Field(type = FieldType.Keyword)
    private String cnName;

    public static TrainStationNameDTO cloneTrainStationName(TrainStationName stationName){
        TrainStationNameDTO dto = new TrainStationNameDTO();
        BeanUtils.copyProperties(stationName, dto);
        return dto;
    }
}

es的查询语句

在不知道如何在代码中拼写语句时,可以先使用es的查询语句试哈。之后再敲代码会清晰许多。

GET /train_station_name/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "prefix": {
            "cnName.keyword": {
              "value": "beib"
            }
          }
        },
        {
          "match_phrase_prefix": {
            "pinyin": "beib"
          }
        }
      ]
    }
  }
}

Java代码实现

spring封装的ElasticsearchRestTemplate实现,没有特殊查询时建议直接用spring封装的工具类

@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;

public Flux<TrainStationNameDTO> findTrainStationName(String keywords) {

    BoolQueryBuilder boolQuery = new BoolQueryBuilder();
    QueryBuilder cnNameQuery = new PrefixQueryBuilder("cnName.keyword", keywords);
    boolQuery.should(cnNameQuery);
    QueryBuilder pinyinQuery = new MatchPhrasePrefixQueryBuilder("pinyin", keywords);
    boolQuery.should(pinyinQuery);
    Query query = new NativeSearchQuery(boolQuery);
    return Flux.fromIterable(elasticsearchRestTemplate.search(query, TrainStationNameDTO.class)).map(SearchHit::getContent);
}

spring封装的orm框架,做简单的crud操作时强烈建议就用这种方式。类似mybatis

@Component
@Document(indexName = "train_station_name")
public interface TrainStationNameRepository extends ElasticsearchRepository<TrainStationNameDTO, Long> {

    /**
     * 查询以keywords开头的站点信息
     * @param cnName 中文
     * @param pinyin 拼音
     * @return 返回结果
     */
    List<TrainStationNameDTO> findByCnNameStartingWithOrPinyinStartingWith(String cnName, String pinyin);

}

最开始的RestHighLevelClient实现

@Autowired
private RestHighLevelClient client;

private void useClient(String keywords) {
    SearchRequest request = new SearchRequest("train_station_name");
    request.source(SearchSourceBuilder.searchSource()
            .query(QueryBuilders.boolQuery()
                    .should(QueryBuilders.prefixQuery("cnName.keyword", keywords))
                    .should(QueryBuilders.matchPhrasePrefixQuery("pinyin", keywords))
            )
    );
    try {
        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
        log.info(JSONObject.toJSONString(search.getHits()));
    } catch (IOException e) {
        e.printStackTrace();
    }
}

关注微信订阅号‘起岸星辰’获取最新资讯

标签:实战,String,pinyin,private,Elasticsearch7,笔记,stationName,new,import
来源: https://blog.csdn.net/Vchar_Fred/article/details/115611451

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有