springboot: 2.3.1.RELEASE
elasticsearch官网:https://www.elastic.co/cn/start
elasticsearch下载:https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.6.2-linux-x86_64.tar.gz
ik 中文分词器:https://github.com/medcl/elasticsearch-analysis-ik/releases
pinyin 拼音分词器:https://github.com/medcl/elasticsearch-analysis-pinyin/releases
商品推荐:https://blog.youkuaiyun.com/zhenghongcs/article/details/105501821
1、安装:
tar -zxvf elasticsearch-7.6.2-linux-x86_64.tar.gz
#修改配置
vi /data/elasticsearch-7.6.2/conf/
node.name: node-1
network.host: IP
#以es用户启动
groupadd es
useradd es -g es -p es
chown -R es:es /data/elasticsearch-7.6.2
su es
cd /data/elasticsearch-7.6.2/bin
./elasticsearch
访问:IP:9200 看下是否安装成功
安装插件:
cd /data/elasticsearch-7.6.2/plugins
解压下载的 ik、pinyin分词器
后台方式重启es
/data/elasticsearch-7.6.2/bin/elasticsearch -d
2、新建springboot项目
pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
application.yml
# 搜索
elasticsearch:
host: 192.168.211.61
port: 9200
配置类
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
@Slf4j
@EnableElasticsearchRepositories(basePackages = "xxxxx")
@Configuration
public class ElasticSearchConfig extends AbstractElasticsearchConfiguration {
@Value("${elasticsearch.host}")
private String host;
@Value("${elasticsearch.port}")
private int port;
// 使用的协议
private String schema = "http";
// 连接超时时间
private int socketTimeOut = 30000;
// 连接超时时间
private int connectTimeOut = 1000;
// 获取连接的超时时间
private int connectionRequestTimeOut = 500;
// 最大连接数
private int maxConnectPerRoute = 100;
// 最大路由连接数
private int maxConnectNum = 100;
@Override
public RestHighLevelClient elasticsearchClient() {
log.info("########## elasticSearchConfig host:{}", host);
RestClientBuilder builder = RestClient.builder(new HttpHost(host, port, schema));
// 异步httpclient连接延时配置
builder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
@Override
public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
requestConfigBuilder.setConnectTimeout(connectTimeOut);
requestConfigBuilder.setSocketTimeout(socketTimeOut);
requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeOut);
return requestConfigBuilder;
}
});
// 异步httpclient连接数配置
builder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
httpClientBuilder.setMaxConnTotal(maxConnectNum);
httpClientBuilder.setMaxConnPerRoute(maxConnectPerRoute);
return httpClientBuilder;
}
});
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
@Bean
public ElasticsearchRestTemplate elasticsearchRestTemplate() {
return new ElasticsearchRestTemplate(elasticsearchClient());
}
}
实体类,如果mapping不存在启动会自动创建
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.*;
import java.math.BigDecimal;
import java.time.LocalDate;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
@Document(indexName = "goods_spu", shards = 3, replicas = 1)
@ApiModel(value = "搜索实体--商品spu")
public class EsGoodsSpu {
@Id
@ApiModelProperty(value = "主键")
private Long spuId;
/**
* SPU编号,分发的商品编号相同
*/
@Field(type = FieldType.Keyword)
@ApiModelProperty(value = "SPU编号,分发的商品编号相同")
private String spuCode;
/**
* 商家id
*/
@ApiModelProperty(value = "商家id")
private Long merchantId;
/**
* 商家名称
*/
@Field(type = FieldType.Keyword, index = false)
@ApiModelProperty(value = "商家名称")
private String merchantName;
/**
* 商品名称
*/
@MultiField(mainField = @Field(type = FieldType.Text, analyzer = "ik_max_word"),
otherFields = @InnerField(suffix = "pinyin", type = FieldType.Text, analyzer = "pinyin", searchAnalyzer = "pinyin"))
@ApiModelProperty(value = "商品名称")
private String spuName;
/**
* 副标题
*/
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
@ApiModelProperty(value = "副标题")
private String subTitle;
/**
* 定位信息
*/
@GeoPointField
@ApiModelProperty(value = "定位完整坐标:精度,维度")
private String position;
/**
* 创建时间
*/
@Field(type = FieldType.Date, format = DateFormat.custom, pattern = "uuuu-MM-dd HH:mm:ss")
@ApiModelProperty(value = "创建时间")
private LocalDate createTime;
}
dao
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface EsGoodsSpuRepository extends ElasticsearchRepository<EsGoodsSpu, Long> {
}
service
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.jkinvest.mp.goods.mapper.EsGoodsSpuRepository;
import cn.jkinvest.mp.goods.pojo.search.EsGoodsSpu;
import cn.jkinvest.mp.goods.pojo.search.SearchParam;
import cn.jkinvest.mp.goods.service.SearchService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortBuilders;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* @Description: 搜索
* @Author zhangdongkang
* @Date 2021/4/25
*/
@Service
public class SearchServiceImpl implements SearchService {
@Resource
private EsGoodsSpuRepository esGoodsSpuRepository;
/**
* @Description: 搜索
* @Author zhangdongkang
* @Date 2021/4/25
*/
@Override
public Page<EsGoodsSpu> search(SearchParam searchParam) {
//分页
Integer pageNumber = searchParam.getPageNumber();
Integer pageSize = searchParam.getPageSize();
if (pageNumber == null) {
pageNumber = 1;
}
pageNumber = pageNumber - 1;
if (pageSize == null) {
pageSize = 10;
}
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
PageRequest pageRequest = PageRequest.of(pageNumber, pageSize);
//关键词匹配
String keywords = searchParam.getKeywords();
if (StrUtil.isNotBlank(keywords)) {
queryBuilder.must(
QueryBuilders.boolQuery()
// spuName IK分词匹配
.should(QueryBuilders.matchQuery("spuName", keywords).boost(2))
// spuName pinyin分词匹配
.should(QueryBuilders.matchQuery("spuName.pinyin", keywords).boost(2))
// 副标题 IK分词匹配
.should(QueryBuilders.matchQuery("subTitle", keywords).boost(1))
);
}
//商家id
Long merchantId = searchParam.getMerchantId();
if (merchantId != null) {
queryBuilder.must(QueryBuilders.termQuery("merchantId", merchantId));
}
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
.withQuery(queryBuilder)
.withPageable(pageRequest)
.withSort(SortBuilders.scoreSort());
Page<EsGoodsSpu> page = esGoodsSpuRepository.search(nativeSearchQueryBuilder.build());
return page;
}
}