其他分享
首页 > 其他分享> > Elasticsearch7学习笔记(实战)

Elasticsearch7学习笔记(实战)

作者:互联网

在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