Elasticsearch7學(xué)習(xí)筆記(上)
Elasticsearch7學(xué)習(xí)筆記(中)
Elasticsearch7學(xué)習(xí)筆記(下)
Elasticsearch7學(xué)習(xí)筆記(實戰(zhàn))
在SpringBoot中集成Elasticsearch,需要添加如下maven依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
注意在這里引入es的jar包版本要比elasticsearch版本相等或大于(最好相等),否則可能會出現(xiàn)一些奇奇怪怪的問題。
在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
示例:查詢以某個字符開頭的數(shù)據(jù)
這里我們實現(xiàn)類似12306查詢站點時的智能提示功能掺逼,即輸入北京會智能顯示北京開頭的站點。下面的示例使用的是webflux
12306火車站點信息數(shù)據(jù)拉取
站點數(shù)據(jù):https://www.12306.cn/index/script/core/common/station_name_v10095.js
數(shù)據(jù)解析程序如下:
private static final String STATION_NAME_URL = "https://www.12306.cn/index/script/core/common/station_name_v10095.js";
/**
* 導(dǎo)入站點數(shù)據(jù)
*/
public Mono<String> importTrainStationName() {
return WebClient.create(STATION_NAME_URL).get().retrieve()
.onStatus(HttpStatus::is4xxClientError, clientResponse-> Mono.error(new BizException("數(shù)據(jù)拉取失敗")))
.bodyToMono(String.class)
.flatMap(body->{
List<TrainStationName> list = extractStationName(body);
return Mono.just(batchInsert(list));
});
}
/**
* 提取數(shù)據(jù)
*/
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;
}
/**
* 導(dǎo)入數(shù)據(jù)到庫中
*/
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條數(shù)據(jù)瓤介,新增:%d條數(shù)據(jù)", totalPull, add);
}
站點數(shù)據(jù)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代碼實現(xiàn)
spring封裝的ElasticsearchRestTemplate實現(xiàn)氯质,沒有特殊查詢時建議直接用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 返回結(jié)果
*/
List<TrainStationNameDTO> findByCnNameStartingWithOrPinyinStartingWith(String cnName, String pinyin);
}
最開始的RestHighLevelClient實現(xiàn)
@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();
}
}