docker安装
# 拉取 ElasticSearch镜像
docker pull elasticsearch:7.6.1
# 拉取 Head 镜像
docker pull mobz/elasticsearch-head:5
# 拉取 Kibana 镜像
docker pull kibana:7.6.1
启动ElasticSearch
docker run -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -d --name elasticsearch -e "discovery.type=single-node" -p 9200:9200 -p 9300:9300 elasticsearch:7.6.1
启动head容器
docker run -d -p 9100:9100 --name es_head docker.io/mobz/elasticsearch-head:5
浏览器访问127.0.0.1:9100
设置跨域
# 查询运行容器 elasticsearch 的 id
docker ps -a
# 进入容器
docker exec -it ******(容器id) /bin/bash
# 进入config目录
cd ./config
# 编辑 elasticsearch.yml 文件
vim elasticsearch.yml
在elasticsearch.yml中添加如下内容
http.cors.enabled: true
http.cors.allow-origin: "*"
重启 ElasticSearch容器
docker restart elasticsearch
启动 kibana 容器
docker run -d -p 5601:5601 --name kibana --link elasticsearch:elasticsearch kibana:7.6.1
汉化
只需要进入kibana容器,在配置文件 kibana.yml 中加入
i18n.locale: "zh-CN"
浏览器访问127.0.0.1:5601
head 无法显示数据问题
通过 Kibana 插入数据后,在head的数据预览页面发现数据没有加载出来,打开检查,发现前端报错406。
进入head容器中,docker exec -it es_head /bin/bash
进入 _site 目录 cd _site/
编辑 vendor.js 共有两处
6886行 contentType: "application/x-www-form-urlencoded" 修改为 contentType: "application/json;charset=UTF-8"
7573行 var inspectData = s.contentType === "application/x-www-form-urlencoded" && 修改为 var inspectData = s.contentType === "application/json;charset=UTF-8" &&
保存退出,不需要重启容器
刷新浏览器,发现数据正确展示。
2、Head 容器中没有vim命令
apt-get install vim
apt-get update
apt-get install vim
安装ik分词插件
将压缩包移动到容器中
docker cp elasticsearch-analysis-ik-7.6.1.zip elasticsearch:/usr/share/elasticsearch/plugins
进入容器
docker exec -it elasticsearch /bin/bash
创建目录
mkdir /usr/share/elasticsearch/plugins/ik
将文件压缩包移动到ik中
mv /usr/share/elasticsearch/plugins/elasticsearch-analysis-ik-7.6.1.zip /usr/share/elasticsearch/plugins/ik
进入目录
cd /usr/share/elasticsearch/plugins/ik
解压
unzip elasticsearch-analysis-ik-7.6.1.zip
删除压缩包
rm -rf elasticsearch-analysis-ik-7.6.1.zip
退出并重启镜像
exit
docker restart elasticsearch
springboot集成ElasticSearch
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
package com.mushi.mushiclient.config;
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.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
/**
* use:
*
* @author gushenme
* @date 2021/3/12 0012 14:07
*/
@Configuration
public class EsConf {
@Value("${elasticsearch.url}")
private String edUrl;
//localhost:9200 写在配置文件中就可以了
@Bean
RestHighLevelClient client() {
ClientConfiguration clientConfiguration = ClientConfiguration.builder()
.connectedTo(edUrl)//elasticsearch地址
.withConnectTimeout(10000)
.build();
return RestClients.create(clientConfiguration).rest();
}
}
# Elasticsearch
elasticsearch:
url: xx.xx.xx:9200
package com.mushi.mushiclient.project.reform2021.entity;
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 java.math.BigDecimal;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.*;
/**
* 集采商城商品信息
*
* @author gumeng
* @email sunlightcs@gmail.com
* @date 2021-01-12 12:08:44
*/
@Data
@TableName("t_purchase_mall_goods")
@Document(indexName = "goods_data")
@Setting(settingPath = "Elasticsearch-setting.json")
@Mapping(mappingPath = "Elasticsearch-mapping.json")
public class TPurchaseMallGoodsEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 商品id
*/
@TableId(value = "id", type = IdType.INPUT)
private String id;
/**
* 商品名称
*/
//elasticsearch查询字段
// @Field(searchAnalyzer = "ik_smart", analyzer = "ik_smart", type = FieldType.Text)
private String goodsName;
/**
* 规格值 新增
*/
//elasticsearch查询字段
// @Field(searchAnalyzer = "ik_smart", analyzer = "ik_smart", type = FieldType.Text)
private String specValue;
/**
* 商品搜索字段
*/
//elasticsearch查询字段
// @Field(searchAnalyzer = "ik_smart", analyzer = "ik_smart", type = FieldType.Text)
private String searchTitle;
/**
* 专业测评
*/
private String professionalAssessment;
/**
* 磨轮-专业测评
*/
private String specialProfessionalAssessment;
/**
* 分类id
*/
private Integer categoryId;
/**
* 主图(与小图等同)
*/
private String mainPic;
/**
* 商品详情图,可以有多张,以逗号隔开
*/
private String detailPic;
/**
* 商品单位 例如,个(桶)
*/
private String unit;
/**
* 排序
*/
private Integer sort;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createDate;
/**
* 更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date updateDate;
/**
* 配送方式 1物流配送 2提付 3物流配送/自提
*/
private String deliveryStyle;
/**
* 起订数量
*/
private Integer minOrderNum;
/**
* 品牌id
*/
private String brandId;
/**
* 品牌名称
*/
private String brandName;
/**
* 生产厂家
*/
private String producedFactory;
/**
* 供应商id
*/
private String supplierSalerId;
/**
* 供应商名称
*/
private String supplierSalerName;
/**
* 首页推荐排序(由大到小)
*/
private Integer indexRecommendSort;
/**
* 0未上架 1上架中 2已下架
*/
private String goodsStatus;
/**
* 商品最低价格【后台生成】
*/
private BigDecimal priceMin;
/**
* 商品最高价格【后台生成】
*/
private BigDecimal priceMax;
/**
* 适用设备或适用材质等【后台生成】
*/
private String applyEquipOrOther;
/**
* 适用设备/材质标题 比如 适用设备
*/
private String applyEquipOrOtherTitle;
/**
* 预计的发货时间 比如4-7 【后台计算】
*/
private String preSendDate;
/**
* 富文本内容
*/
private String richContent;
/**
* 总销量
*/
private Long totalSaleNum;
/**
* 特殊跳转
*/
private String specialJump;
/**
* 视频详情
*/
private String videoDetail;
/**
* 视频背景图
*/
private String videoPic;
/**
* 品牌名称
*/
private String brandNameNew;
/**
* 进货价格
*/
private BigDecimal purchasePrice;
/**
* 运费模板id
*/
private Long templateId;
/**
* 会员价格
*/
@TableField(exist = false)
private List<TPurchaseMallGoodsMemberAttrEntity> memberPriceList;
/**
* 非会员价格
*/
@TableField(exist = false)
private List<TPurchaseMallGoodsMemberAttrEntity> nonMemberPriceList;
@TableField(exist = false)
private Long goodsSales;
/**
* 热销爆款 类型 1-首页 2-一级商品分类 3-二级商品分类
*/
@TableField(exist = false)
private Integer goodsHotType;
@TableField(exist = false)
private String supplierSalerProvinceId;
@TableField(exist = false)
private String supplierSalerCityId;
@TableField(exist = false)
private String supplierSalerCountyId;
@TableField(exist = false)
private String supplierSalerCityName;
@TableField(exist = false)
private String supplierSalerProvinceName;
@TableField(exist = false)
private String supplierSalerCountyName;
@TableField(exist = false)
private String supplierSalerLogo;
/**
* 属性list
*/
@TableField(exist = false)
private List<TPurchaseMallGoodsAttrVo> attrList;
@TableField(exist = false)
private List<String> goodsIdsList;
@TableField(exist = false)
private String attrJson;
}
package com.mushi.mushiclient.project.reform2021.elasticsearch;
import com.mushi.mushiclient.project.reform2021.entity.TPurchaseMallGoodsEntity;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* use: elasticsearch 商品操作接口
*
* @author gushenme
* @date 2021/3/12 0012 13:12
*/
public interface EsProductRepository extends ElasticsearchRepository<TPurchaseMallGoodsEntity, String> {
Page<TPurchaseMallGoodsEntity> findByGoodsName(String goodsName,Pageable page);
Page<TPurchaseMallGoodsEntity> findByGoodsNameAndSpecValueAndSearchTitleAndProfessionalAssessmentAndSpecialProfessionalAssessment(String goodsName, String specValue, String searchTitle, String assessment, String specialAssessment,Pageable page);
}
package com.mushi.mushiclient.project.reform2021.service.elasticsearch;
import com.mushi.mushiclient.project.reform2021.entity.TPurchaseMallGoodsEntity;
import org.springframework.data.domain.Page;
import java.util.List;
/**
* use: 商品搜索
*
* @author gushenme
* @date 2021/3/12 0012 13:17
*/
public interface EsProductService {
/**
* 从数据库中导入所有商品到ES
*/
int importAll();
/**
* 根据id删除商品
*/
void delete(String id);
/**
* 根据id创建商品
*/
TPurchaseMallGoodsEntity create(String id);
/**
* 批量删除商品
*/
void delete(List<String> ids);
/**
* 删除所有商品
*/
void deleteAll();
/**
* 根据关键字搜索名称或者副标题
*/
Page<TPurchaseMallGoodsEntity> search(String keyWord, Integer pageNum, Integer pageSize);
}
package com.mushi.mushiclient.project.reform2021.service.elasticsearch.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.itextpdf.text.log.Logger;
import com.itextpdf.text.log.LoggerFactory;
import com.mushi.mushiclient.project.reform2021.elasticsearch.EsProductRepository;
import com.mushi.mushiclient.project.reform2021.entity.TPurchaseMallGoodsEntity;
import com.mushi.mushiclient.project.reform2021.service.TPurchaseMallGoodsService;
import com.mushi.mushiclient.project.reform2021.service.elasticsearch.EsProductService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* use: 商品搜索实现类
*
* @author gushenme
* @date 2021/3/12 0012 13:18
*/
@Service
public class EsProductServiceImpl implements EsProductService {
private static final Logger LOGGER = LoggerFactory.getLogger(EsProductServiceImpl.class);
@Autowired
private TPurchaseMallGoodsService tPurchaseMallGoodsService;
@Autowired
private EsProductRepository productRepository;
@Override
public int importAll() {
QueryWrapper<TPurchaseMallGoodsEntity> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("goods_status", 1);
List<TPurchaseMallGoodsEntity> esProductList = tPurchaseMallGoodsService.list(queryWrapper);
Iterable<TPurchaseMallGoodsEntity> esProductIterable = productRepository.saveAll(esProductList);
Iterator<TPurchaseMallGoodsEntity> iterator = esProductIterable.iterator();
int result = 0;
while (iterator.hasNext()) {
result++;
iterator.next();
}
return result;
}
@Override
public void delete(String id) {
productRepository.deleteById(id);
}
@Override
public TPurchaseMallGoodsEntity create(String id) {
TPurchaseMallGoodsEntity result = null;
TPurchaseMallGoodsEntity esProduct = tPurchaseMallGoodsService.getById(id);
result = productRepository.save(esProduct);
return result;
}
@Override
public void delete(List<String> ids) {
if (!CollectionUtils.isEmpty(ids)) {
List<TPurchaseMallGoodsEntity> esProductList = new ArrayList<>();
for (String id : ids) {
TPurchaseMallGoodsEntity TPurchaseMallGoodsEntity = new TPurchaseMallGoodsEntity();
TPurchaseMallGoodsEntity.setId(id);
esProductList.add(TPurchaseMallGoodsEntity);
}
productRepository.deleteAll(esProductList);
}
}
@Override
public void deleteAll() {
productRepository.deleteAll();
}
@Override
public Page<TPurchaseMallGoodsEntity> search(String keyWord, Integer pageNum, Integer pageSize) {
Pageable pageable = PageRequest.of(pageNum, pageSize);
return productRepository.findByGoodsName(keyWord, pageable);
}
}
Elasticsearch-setting.json
此处实现处理分词 毫米转为mm
lowercase作用是不区分英文大小写
{
"index": {
"analysis": {
"analyzer": {
"mm_transfer_analyzer": {
"tokenizer": "ik_max_word",
"char_filter": "mapping_char_filter",
"filter": "lowercase"
}
},
"char_filter": {
"mapping_char_filter": {
"type": "mapping",
"mappings": [
"毫米 => mm"
]
}
}
}
}
}
Elasticsearch-mapping.json
{
"properties": {
"goodsName": {
"type": "text",
"analyzer": "mm_transfer_analyzer",
"search_analyzer": "mm_transfer_analyzer"
},
"specValue": {
"type": "text",
"analyzer": "mm_transfer_analyzer",
"search_analyzer": "mm_transfer_analyzer"
},
"searchTitle": {
"type": "text",
"analyzer": "mm_transfer_analyzer",
"search_analyzer": "mm_transfer_analyzer"
}
}
}
接口调用其分页查询
/**
* @Description: 首页-商品分类-商品列表 接口<br>
* @Param: [username, password]
* @Return: com.mushi.mushiclient.crm.domain.AjaxResultObject
* @Author: gushenme
* @Date: 2021/1/9 0009 13:20
*/
@ApiOperation(value = "查询首页-商品分类-商品列表 接口", notes = "查询首页-商品分类-商品列表 信息", tags = "查询首页-商品分类-商品列表 信息")
@PostMapping(value = "/getGoodsList")
public AjaxResultObject getGoodsList(Integer pageNo, Integer pageSize, String searchValue, String categoryId, String brandId, Integer priceSort) {
if (pageNo == null || pageSize == null) {
return AjaxResultObject.error("参数不完整");
}
try {
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
BoolQueryBuilder bool = QueryBuilders.boolQuery();
List<TPurchaseMallGoodsEntity> list = new ArrayList<>();
QueryWrapper<TPurchaseMallGoodsEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("goods_status", 1);
bool.must(QueryBuilders.termQuery("goodsStatus", 1));
// TODO: 2021/2/5 0005 关键词搜索
if (StringUtils.isNotEmpty(searchValue)) {
queryWrapper.and(wrap -> wrap.like("search_title", searchValue).or().like("goods_name", searchValue).or().like("spec_value", searchValue));
bool.must(QueryBuilders.boolQuery()
.should(QueryBuilders.matchQuery("goodsName", searchValue).boost(50))
.should(QueryBuilders.matchQuery("searchTitle", searchValue).boost(10))
.should(QueryBuilders.matchQuery("specValue", searchValue).boost(30)));
}
// TODO: 2021/2/5 0005 商品分类
if (StringUtils.isNotEmpty(categoryId)) {
// TODO: 2021/2/5 0005 递归查询其子分类
List<Integer> categoryList = getAllOrgidsTwo(Integer.parseInt(categoryId));
System.out.println("---------------" + categoryList);
// TODO: 2021/2/5 0005 查询该分类下的商品id
String redisKey_GoodsCategoryRelation = "BSHC_my_goods_category_relation_category_id_in_" + categoryList.toString();
QueryWrapper<TPurchaseMallGoodsCategoryRelationEntity> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.in("category_id", categoryList).groupBy("goods_id");
List<TPurchaseMallGoodsCategoryRelationEntity> goodsCategoryRelationEntityList = new ArrayList<>();
if (StringUtils.isNull(redisTemplate.opsForValue().get(redisKey_GoodsCategoryRelation))) {
goodsCategoryRelationEntityList = tPurchaseMallGoodsCategoryRelationService.list(queryWrapper1);
redisTemplate.opsForValue().set(redisKey_GoodsCategoryRelation, JSON.toJSON(goodsCategoryRelationEntityList).toString(), 60, TimeUnit.MINUTES);
} else {
goodsCategoryRelationEntityList = JSONObject.parseArray(redisTemplate.opsForValue().get(redisKey_GoodsCategoryRelation).toString(), TPurchaseMallGoodsCategoryRelationEntity.class);
}
// QueryWrapper<TPurchaseMallGoodsCategoryRelationEntity> queryWrapper1 = new QueryWrapper<>();
// queryWrapper1.in("category_id", categoryList).groupBy("goods_id");
// List<TPurchaseMallGoodsCategoryRelationEntity> goodsCategoryRelationEntityList = tPurchaseMallGoodsCategoryRelationService.list(queryWrapper1);
System.out.println("-----------------" + goodsCategoryRelationEntityList);
List<String> goodsIdList = goodsCategoryRelationEntityList.stream().map(t -> t.getGoodsId()).collect(Collectors.toList());
if (goodsIdList.size() > 0) {
queryWrapper.in("id", goodsIdList);
bool.must(QueryBuilders.termsQuery("id", goodsIdList));
} else {
Map<String, Object> rs = new HashMap<>();
rs.put("totalCount", 0);
rs.put("goodsList", list);
return AjaxResultObject.success(rs);
}
}
// TODO: 2021/2/5 0005 品牌 即供应商
if (StringUtils.isNotEmpty(brandId)) {
queryWrapper.eq("supplier_saler_id", brandId);
bool.must(QueryBuilders.termQuery("supplierSalerId", brandId));
}
searchQueryBuilder.withQuery(bool);
// TODO: 2021/2/5 0005 商品价格排序
// if (priceSort != null) {
// // TODO: 2021/2/5 0005 按价格排序 1-降序 2-升序
// if (priceSort == 1) {
// queryWrapper.orderByDesc("price_max");
// searchQueryBuilder.withSort(SortBuilders.fieldSort("priceMax").order(SortOrder.DESC));
// } else if (priceSort == 2) {
// queryWrapper.orderByAsc("price_max");
// searchQueryBuilder.withSort(SortBuilders.fieldSort("priceMax").order(SortOrder.ASC));
// }
// }
// searchQueryBuilder.withSort(SortBuilders.fieldSort("createDate").order(SortOrder.DESC));
// Page page = PageHelper.startPage(pageNo, pageSize);
// list = tPurchaseMallGoodsService.list(queryWrapper);
Pageable pageable = PageRequest.of(pageNo - 1, pageSize);
searchQueryBuilder.withPageable(pageable);
NativeSearchQuery searchQuery = searchQueryBuilder.build();
logger.info("##################################################################DSL:{}", searchQuery.getQuery().toString());
org.springframework.data.domain.Page<TPurchaseMallGoodsEntity> searchResult = productRepository.search(searchQuery);
list = searchResult.getContent();
list.stream().forEach(goods -> {
// TODO: 2021/2/5 0005 设置会员价格
String redisKey_member_price = "BSHC_goods_member_price_attr_goods_id_" + goods.getId() + "_type_1";
QueryWrapper<TPurchaseMallGoodsMemberAttrEntity> queryWrapperMemberPrice = new QueryWrapper<>();
queryWrapperMemberPrice.eq("goods_id", goods.getId());
queryWrapperMemberPrice.eq("type", 1);
List<TPurchaseMallGoodsMemberAttrEntity> goodsMemberAttrEntityList = new ArrayList<>();
if (StringUtils.isNull(redisTemplate.opsForValue().get(redisKey_member_price))) {
goodsMemberAttrEntityList = tPurchaseMallGoodsMemberAttrService.list(queryWrapperMemberPrice);
redisTemplate.opsForValue().set(redisKey_member_price, JSON.toJSON(goodsMemberAttrEntityList).toString(), 60, TimeUnit.MINUTES);
} else {
goodsMemberAttrEntityList = JSONObject.parseArray(redisTemplate.opsForValue().get(redisKey_member_price).toString(), TPurchaseMallGoodsMemberAttrEntity.class);
}
goodsMemberAttrEntityList.stream().forEach(m -> {
m.setUnit(goods.getUnit());
});
goods.setMemberPriceList(goodsMemberAttrEntityList);
// TODO: 2021/2/5 0005 设置非会员价格
String redisKey_non_member_price = "BSHC_goods_non_member_price_attr_goods_id_" + goods.getId() + "_type_2";
QueryWrapper<TPurchaseMallGoodsMemberAttrEntity> queryWrapperNonMemberPrice = new QueryWrapper<>();
queryWrapperNonMemberPrice.eq("goods_id", goods.getId());
queryWrapperNonMemberPrice.eq("type", 2);
List<TPurchaseMallGoodsMemberAttrEntity> goodsNonMemberAttrEntityList = new ArrayList<>();
if (StringUtils.isNull(redisTemplate.opsForValue().get(redisKey_non_member_price))) {
goodsNonMemberAttrEntityList = tPurchaseMallGoodsMemberAttrService.list(queryWrapperNonMemberPrice);
redisTemplate.opsForValue().set(redisKey_non_member_price, JSON.toJSON(goodsNonMemberAttrEntityList).toString(), 60, TimeUnit.MINUTES);
} else {
goodsNonMemberAttrEntityList = JSONObject.parseArray(redisTemplate.opsForValue().get(redisKey_non_member_price).toString(), TPurchaseMallGoodsMemberAttrEntity.class);
}
goodsNonMemberAttrEntityList.stream().forEach(m -> {
m.setUnit(goods.getUnit());
});
goods.setNonMemberPriceList(goodsNonMemberAttrEntityList);
// TODO: 2021/2/5 0005 1.1查询供应商地址信息
String redisKey_supplier = "BSHC_supplier_id_" + goods.getSupplierSalerId();
TPurchaseMallSupplierSalerEntity supplierSalerEntity = new TPurchaseMallSupplierSalerEntity();
if (StringUtils.isNull(redisTemplate.opsForValue().get(redisKey_supplier))) {
supplierSalerEntity = tPurchaseMallSupplierSalerService.selectSupplierSalerInfo(goods.getSupplierSalerId());
redisTemplate.opsForValue().set(redisKey_supplier, JSON.toJSON(supplierSalerEntity).toString(), 60, TimeUnit.MINUTES);
} else {
supplierSalerEntity = JSONObject.parseObject(redisTemplate.opsForValue().get(redisKey_supplier).toString(), TPurchaseMallSupplierSalerEntity.class);
}
goods.setSupplierSalerProvinceId(supplierSalerEntity.getProvinceId());
goods.setSupplierSalerCityId(supplierSalerEntity.getCityId());
goods.setSupplierSalerCountyId(supplierSalerEntity.getCountyId());
goods.setSupplierSalerProvinceName(supplierSalerEntity.getProvinceName());
goods.setSupplierSalerCityName(supplierSalerEntity.getCityName());
goods.setSupplierSalerCountyName(supplierSalerEntity.getCountyName());
});
list.stream().forEach(g -> {
g.setPurchasePrice(null);
});
Map<String, Object> rs = new HashMap<>();
rs.put("totalCount", searchResult.getTotalElements());
rs.put("goodsList", list);
return AjaxResultObject.success(rs);
} catch (Exception e) {
e.printStackTrace();
}
return AjaxResultObject.error();
}
设置elasticsearch配置账号密码
切换到 elasticsearch 安装文件目录 bin 下 :示例:/usr/local/elasticsearch-7.4.0/bin
借助elasticsearch-certutil命令生成证书:
./elasticsearch-certutil ca -out config/certs/elastic-certificates.p12 -pass
chmod 授权 config/certs下的p12文件
配置通信证书 > 需要在 config目前下elasticsearch.yml 配置
# 开启xpack
xpack.security.enabled: true
xpack.license.self_generated.type: basic
xpack.security.transport.ssl.enabled: true
# 证书配置
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: certs/elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: certs/elastic-certificates.p12
其它配置(可选)
#跨域配置
http.cors.enabled: true
http.cors.allow-origin: "*"
http.cors.allow-headers: Authorization,X-Requested-With,Content-Length,Content-Type
重启elasticsearch
执行设置用户名和密码的命令,内置了部分用户
切换到 elasticsearch 安装文件目录 bin 下 :示例:/usr/local/elasticsearch-7.4.0/bin/
手动配置每个用户密码模式(需要一个一个的输入)
./elasticsearch-setup-passwords interactive
kibana.yml配置
server.name: kibana
server.host: "0"
kibana.index: ".kibana"
elasticsearch.hosts: [ "http://192.168.147.129:9200" ]
xpack.monitoring.ui.container.elasticsearch.enabled: true
i18n.locale: zh-CN
elasticsearch.username: 'kibana'
elasticsearch.password: 'Es123456'
http://ip:9200 账号密码 :elastic 123456
http://ip:9100?auth_user=elastic&auth_password=123456
http://ip:5601/ 账号密码 :elastic 123456
springboot修改elasticSearch配置
@Configuration
public class EsConf {
@Value("${elasticsearch.url}")
private String edUrl;
@Value("${elasticsearch.host}")
private String host;
@Value("${elasticsearch.port}")
private String port;
@Value("${elasticsearch.username}")
private String username;
@Value("${elasticsearch.password}")
private String password;
// @Bean
// RestHighLevelClient client() {
// ClientConfiguration clientConfiguration = ClientConfiguration.builder()
// .connectedTo(edUrl)//elasticsearch地址
// .withConnectTimeout(10000)
// .build();
//
// return RestClients.create(clientConfiguration).rest();
// }
@Bean
public RestHighLevelClient client() {
/*用户认证对象*/
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
/*设置账号密码*/
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
/*创建rest client对象*/
RestClientBuilder builder = RestClient.builder(new HttpHost(host, Integer.parseInt(port)))
.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
return httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
}
});
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
}
RestHighLevelClient工具类
package com.mushi.mushiclient.util;
import com.alibaba.fastjson.JSON;
import com.mushi.mushiclient.project.reform2021.entity.TPurchaseMallGoodsEntity;
import org.apache.poi.ss.formula.functions.T;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* use:
*
* @author gushenme
* @date 2021/3/19 0019 9:06
*/
@Component
public class EsUtils {
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
/**
* 判断索引是否存在
*
* @param index
* @return
* @throws IOException
*/
public boolean existsIndex(String index) throws IOException {
GetIndexRequest request = new GetIndexRequest(index);
boolean exists = client.indices().exists(request,
RequestOptions.DEFAULT);
return exists;
}
/**
* 创建索引
*
* @param index
* @throws IOException
*/
public boolean createIndex(String index) throws IOException {
CreateIndexRequest request = new CreateIndexRequest(index);
CreateIndexResponse createIndexResponse
= client.indices().create(request, RequestOptions.DEFAULT);
return createIndexResponse.isAcknowledged();
}
/**
* 删除索引
*
* @param index
* @return
* @throws IOException
*/
public boolean deleteIndex(String index) throws IOException {
DeleteIndexRequest deleteIndexRequest = new
DeleteIndexRequest(index);
AcknowledgedResponse response =
client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
return response.isAcknowledged();
}
/**
* 判断某索引下文档id是否存在
*
* @param index
* @param id
* @return
* @throws IOException
*/
public boolean docExists(String index, String id) throws IOException {
GetRequest getRequest = new GetRequest(index, id);
//只判断索引是否存在不需要获取_source
getRequest.fetchSourceContext(new FetchSourceContext(false));
getRequest.storedFields("_none_");
boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
return exists;
}
/**
* 添加文档记录
*
* @param index
* @param id
* @param t 要添加的数据实体类
* @return
* @throws IOException
*/
public boolean addDoc(String index, String id, Object t) throws IOException {
IndexRequest request = new IndexRequest(index);
request.id(id);
//timeout
// request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
request.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
request.source(JSON.toJSONString(t), XContentType.JSON);
IndexResponse indexResponse = client.index(request,
RequestOptions.DEFAULT);
RestStatus Status = indexResponse.status();
return Status == RestStatus.OK || Status == RestStatus.CREATED;
}
/**
* 根据id来获取记录
*
* @param index
* @param id
* @return
* @throws IOException
*/
public GetResponse getDoc(String index, String id) throws IOException {
GetRequest request = new GetRequest(index, id);
GetResponse getResponse = client.get(request,
RequestOptions.DEFAULT);
return getResponse;
}
/**
* 批量添加文档记录
* 没有设置id ES会自动生成一个,如果要设置 IndexRequest的对象.id()即可
*
* @param index
* @param list
* @return
* @throws IOException
*/
public boolean bulkAdd(String index, List<TPurchaseMallGoodsEntity> list) throws IOException {
BulkRequest bulkRequest = new BulkRequest();
//timeout
bulkRequest.timeout(TimeValue.timeValueMinutes(2));
bulkRequest.timeout("2m");
bulkRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
for (int i = 0; i < list.size(); i++) {
bulkRequest.add(new IndexRequest(index).id(list.get(i).getId())
.source(JSON.toJSONString(list.get(i)),XContentType.JSON));
}
BulkResponse bulkResponse = client.bulk(bulkRequest,
RequestOptions.DEFAULT);
return !bulkResponse.hasFailures();
}
/**
* 批量删除和更新就不写了可根据上面几个方法来写
*/
/**
* 更新文档记录
*
* @param index
* @param id
* @param t
* @return
* @throws IOException
*/
public boolean updateDoc(String index, String id, Object t) throws IOException {
UpdateRequest request = new UpdateRequest(index, id);
request.doc(JSON.toJSONString(t));
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
UpdateResponse updateResponse = client.update(
request, RequestOptions.DEFAULT);
return updateResponse.status() == RestStatus.OK;
}
/**
* 删除文档记录
*
* @param index
* @param id
* @return
* @throws IOException
*/
public boolean deleteDoc(String index, String id) throws IOException {
DeleteRequest request = new DeleteRequest(index, id);
//timeout
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
DeleteResponse deleteResponse = client.delete(
request, RequestOptions.DEFAULT);
return deleteResponse.status() == RestStatus.OK;
}
/**
* 根据某字段来搜索
*
* @param index
* @param field
* @param key 要收搜的关键字
* @throws IOException
*/
public void search(String index, String field, String key, Integer
from, Integer size) throws IOException {
SearchRequest searchRequest = new SearchRequest(index);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.termQuery(field, key));
//控制搜素
sourceBuilder.from(from);
sourceBuilder.size(size);
//最大搜索时间。
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = client.search(searchRequest,
RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(searchResponse.getHits()));
}
}
使用RestHighLevelClient工具类写增删查改接口
package com.mushi.mushiclient.project.reform2021.controller;
import com.google.common.collect.Lists;
import com.mushi.mushiclient.crm.domain.AjaxResultObject;
import com.mushi.mushiclient.project.reform2021.elasticsearch.EsProductRepository;
import com.mushi.mushiclient.project.reform2021.entity.TPurchaseMallGoodsEntity;
import com.mushi.mushiclient.project.reform2021.service.elasticsearch.EsProductService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery;
import org.elasticsearch.index.query.*;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
* use:
*
* @author gushenme
* @date 2021/3/12 0012 14:55
*/
@Controller
@Api(tags = "EsProductController", description = "搜索商品管理")
@RequestMapping("/esProduct")
//@CrossOrigin
public class EsProductController {
Logger logger = LoggerFactory.getLogger(EsProductController.class);
@Autowired
private EsProductService esProductService;
@Autowired
private EsProductRepository productRepository;
private ElasticsearchTemplate elasticsearchTemplate;
/**
* @Description: 根据id查询elasticsearch商品<br>
* @Param: []
* @Return: com.mushi.mushiclient.crm.domain.AjaxResultObject
* @Author: gushenme
* @Date: 2021/4/10 0010 11:26
*/
@ApiOperation(value = "根据id查询elasticsearch商品")
@RequestMapping(value = "/getGoodsById", method = RequestMethod.POST)
@ResponseBody
public AjaxResultObject getGoodsById(String goodsId) {
TPurchaseMallGoodsEntity goods = esProductService.getById(goodsId);
return AjaxResultObject.success(goods);
}
/**
* @Description: 拼接商品组商品 导入所有商品组数据到ES<br>
* @Param: []
* @Return: com.mushi.mushiclient.crm.domain.AjaxResultObject
* @Author: gushenme
* @Date: 2021/4/10 0010 11:26
*/
@ApiOperation(value = "导入所有商品组数据到ES")
@RequestMapping(value = "/importGroupGoods", method = RequestMethod.POST)
@ResponseBody
public AjaxResultObject importGroupGoodsList() {
Boolean count = esProductService.importAllGroupGoods();
return AjaxResultObject.success(count);
}
@ApiOperation(value = "导入所有商品数据到ES")
@RequestMapping(value = "/importAll", method = RequestMethod.POST)
@ResponseBody
public AjaxResultObject importAllList() {
Boolean count = esProductService.importAll();
return AjaxResultObject.success(count);
}
@ApiOperation(value = "根据id删除商品")
@RequestMapping(value = "/delete/{id}", method = RequestMethod.GET)
@ResponseBody
public AjaxResultObject delete(@PathVariable String id) {
return AjaxResultObject.success(esProductService.delete(id));
}
@ApiOperation(value = "删除所有商品")
@RequestMapping(value = "/deleteAll", method = RequestMethod.POST)
@ResponseBody
public AjaxResultObject deleteAll() {
esProductService.deleteAll();
return AjaxResultObject.success(null);
}
@ApiOperation(value = "根据id批量删除商品")
@RequestMapping(value = "/delete/batch", method = RequestMethod.POST)
@ResponseBody
public AjaxResultObject delete(@RequestParam("ids") List<String> ids) {
esProductService.delete(ids);
return AjaxResultObject.success(null);
}
@ApiOperation(value = "根据id创建商品")
@RequestMapping(value = "/create/{id}", method = RequestMethod.POST)
@ResponseBody
public AjaxResultObject create(@PathVariable String id) {
Boolean esProduct = esProductService.create(id);
if (esProduct != null) {
return AjaxResultObject.success(esProduct);
} else {
return AjaxResultObject.error();
}
}
@ApiOperation(value = "简单搜索")
@RequestMapping(value = "/search/simple", method = RequestMethod.POST)
@ResponseBody
public AjaxResultObject search(@RequestParam(required = false) String keyword,
@RequestParam(required = false, defaultValue = "0") Integer pageNum,
@RequestParam(required = false, defaultValue = "10") Integer pageSize) {
Pageable pageable = PageRequest.of(pageNum, pageSize);
// 1.创建查询对象
// HighlightBuilder highlightBuilder=new HighlightBuilder();
// highlightBuilder.preTags("<span style='color:red'>");
// highlightBuilder.postTags("</span>");
// highlightBuilder.field("goodsName");
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("goodsStatus", "1"))
.must(QueryBuilders.boolQuery()
.should(QueryBuilders.matchQuery("goodsName", keyword))
.should(QueryBuilders.matchQuery("searchTitle", keyword))
.should(QueryBuilders.matchQuery("specValue", keyword)))
).withSort(SortBuilders.fieldSort("createDate").order(SortOrder.DESC))
// .withHighlightBuilder(highlightBuilder)
// .withPageable(PageRequest.of(pageNum - 1, pageSize))
.build();
// 2.调用查询接口
// Page<TPurchaseMallGoodsEntity> search = productRepository.search(queryBuilder, pageable);
Page<TPurchaseMallGoodsEntity> search = productRepository.search(searchQuery);
logger.info("##################################################################DSL:{}", searchQuery.getQuery().toString());
return AjaxResultObject.success(search);
}
@ApiOperation(value = "根据商品组id创建商品组商品")
@RequestMapping(value = "/createGroupGoods/{id}", method = RequestMethod.POST)
@ResponseBody
public AjaxResultObject createGroupGoods(@PathVariable Long id) {
Boolean esProduct = esProductService.createGroupGoods(id);
if (esProduct != null) {
return AjaxResultObject.success(esProduct);
} else {
return AjaxResultObject.error();
}
}
}
package com.mushi.mushiclient.project.reform2021.service.elasticsearch;
import com.mushi.mushiclient.project.reform2021.entity.TPurchaseMallGoodsEntity;
import org.springframework.data.domain.Page;
import java.io.IOException;
import java.util.List;
/**
* use: 商品搜索
*
* @author gushenme
* @date 2021/3/12 0012 13:17
*/
public interface EsProductService {
/**
* 从数据库中导入所有商品到ES
*/
Boolean importAll();
/**
* 根据id删除商品
*/
Boolean delete(String id);
/**
* 根据id创建商品
*/
Boolean create(String id);
/**
* 批量删除商品
*/
void delete(List<String> ids);
/**
* 删除所有商品
*/
void deleteAll();
/**
* 根据关键字搜索名称或者副标题
*/
Page<TPurchaseMallGoodsEntity> search(String keyWord, Integer pageNum, Integer pageSize);
/**
* 导入所有商品组数据到ES
*/
Boolean importAllGroupGoods();
/*
* @Description: 根据id查询elasticsearch商品<br>
* @Param:
* @Return:
* @Author: gushenme
* @Date: 2021/4/10 0010 16:34
*/
TPurchaseMallGoodsEntity getById(String goodsId);
/**
* @Description: 导入商品组商品到es<br>
* @Param:
* @Return:
* @Author: gushenme
* @Date: 2021/5/8 0008 10:35
*/
Boolean createGroupGoods(Long goodsRelationId);
}
package com.mushi.mushiclient.project.reform2021.service.elasticsearch.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.itextpdf.text.log.Logger;
import com.itextpdf.text.log.LoggerFactory;
import com.mushi.mushiclient.crm.utils.StringUtils;
import com.mushi.mushiclient.project.reform2021.elasticsearch.EsProductRepository;
import com.mushi.mushiclient.project.reform2021.entity.TPurchaseMallGoodsCategoryRelationEntity;
import com.mushi.mushiclient.project.reform2021.entity.TPurchaseMallGoodsEntity;
import com.mushi.mushiclient.project.reform2021.entity.TPurchaseMallGoodsRelationEntity;
import com.mushi.mushiclient.project.reform2021.service.TPurchaseMallGoodsCategoryRelationService;
import com.mushi.mushiclient.project.reform2021.service.TPurchaseMallGoodsRelationService;
import com.mushi.mushiclient.project.reform2021.service.TPurchaseMallGoodsService;
import com.mushi.mushiclient.project.reform2021.service.elasticsearch.EsProductService;
import com.mushi.mushiclient.util.EsUtils;
import com.mushi.mushiclient.util.IdGen;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.common.document.DocumentField;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* use: 商品搜索实现类
*
* @author gushenme
* @date 2021/3/12 0012 13:18
*/
@Service
public class EsProductServiceImpl implements EsProductService {
private static final Logger LOGGER = LoggerFactory.getLogger(EsProductServiceImpl.class);
@Autowired
private TPurchaseMallGoodsService tPurchaseMallGoodsService;
@Autowired
private TPurchaseMallGoodsRelationService tPurchaseMallGoodsRelationService;
@Autowired
private EsProductRepository productRepository;
@Autowired
private EsUtils esUtils;
@Value("${elasticsearch.goods_index_name}")
private String elasticsearchIndexName;
@Autowired
private TPurchaseMallGoodsCategoryRelationService tPurchaseMallGoodsCategoryRelationService;
@Autowired
private StringRedisTemplate redisTemplate;
@Override
public Boolean importAllGroupGoods() {
Boolean rs = false;
try {
//查询group_main_goods_id group_name group_search_title不为null的所有商品组数据
QueryWrapper<TPurchaseMallGoodsRelationEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.isNotNull("group_main_goods_id").isNotNull("group_name").isNotNull("group_search_title").isNotNull("group_goods_id");
List<TPurchaseMallGoodsRelationEntity> goodsRelationEntityList = tPurchaseMallGoodsRelationService.list(queryWrapper);
List<TPurchaseMallGoodsEntity> esProductList = new ArrayList<>();
List<TPurchaseMallGoodsCategoryRelationEntity> esProductCategoryList = new ArrayList<>();
goodsRelationEntityList.stream().forEach(gr -> {
String groupName = gr.getGroupName();
String groupSearchTitle = gr.getGroupSearchTitle();
String groupMainGoodsId = gr.getGroupMainGoodsId();
String groupGoodsId = gr.getGroupGoodsId();
String goodsIds = gr.getGoodsIds();
//查询商品组主商品详情
TPurchaseMallGoodsEntity goodsEntityGroupMain = tPurchaseMallGoodsService.getById(groupMainGoodsId);
//查询商品组所有商品分类
List<String> goodsIdsList = Arrays.asList(goodsIds.split(","));
String redisKey_NonPageGoodsCategoryRelation = "BSHC_my_goods_category_relation_goods_id_in_" + goodsIdsList.toString();
QueryWrapper<TPurchaseMallGoodsCategoryRelationEntity> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.in("goods_id", goodsIdsList).groupBy("category_id");
List<TPurchaseMallGoodsCategoryRelationEntity> goodsCategoryRelationEntityList = new ArrayList<>();
if (StringUtils.isNull(redisTemplate.opsForValue().get(redisKey_NonPageGoodsCategoryRelation))) {
goodsCategoryRelationEntityList = tPurchaseMallGoodsCategoryRelationService.list(queryWrapper1);
redisTemplate.opsForValue().set(redisKey_NonPageGoodsCategoryRelation, JSON.toJSON(goodsCategoryRelationEntityList).toString(), 10, TimeUnit.MINUTES);
} else {
goodsCategoryRelationEntityList = JSONObject.parseArray(redisTemplate.opsForValue().get(redisKey_NonPageGoodsCategoryRelation).toString(), TPurchaseMallGoodsCategoryRelationEntity.class);
}
//替换商品组主商品 id goodsName searchTitle
// String goodsIdGroup = IdGen.uuid();
goodsEntityGroupMain.setId(groupGoodsId);
goodsEntityGroupMain.setGoodsName(groupName);
goodsEntityGroupMain.setSearchTitle(groupSearchTitle);
goodsEntityGroupMain.setSpecValue(null);
// goodsEntityGroupMain.setSupplierSalerId(null);
// goodsEntityGroupMain.setSupplierSalerName(null);
//设置商品组主商品 goodsFromFlag goodsFromFlag2GroupId
goodsEntityGroupMain.setGoodsFromFlag(2);
goodsEntityGroupMain.setGoodsFromFlag2GroupId(gr.getId());
esProductList.add(goodsEntityGroupMain);
goodsCategoryRelationEntityList.stream().forEach(gcr -> {
TPurchaseMallGoodsCategoryRelationEntity goodsCategoryRelationEntity = new TPurchaseMallGoodsCategoryRelationEntity();
goodsCategoryRelationEntity.setGoodsId(groupGoodsId);
goodsCategoryRelationEntity.setCategoryId(gcr.getCategoryId());
esProductCategoryList.add(goodsCategoryRelationEntity);
});
});
rs = esUtils.bulkAdd(elasticsearchIndexName, esProductList);
//保存商品分类
if (rs) {
esProductCategoryList.stream().forEach(epc -> {
//先删除已有的商品分类
QueryWrapper<TPurchaseMallGoodsCategoryRelationEntity> qwRemove = new QueryWrapper<>();
qwRemove.eq("goods_id", epc.getGoodsId()).eq("category_id", epc.getCategoryId());
tPurchaseMallGoodsCategoryRelationService.remove(qwRemove);
//新增新的商品分类
tPurchaseMallGoodsCategoryRelationService.save(epc);
});
}
} catch (IOException e) {
e.printStackTrace();
}
return rs;
}
@Override
public Boolean importAll() {
Boolean rs = false;
try {
QueryWrapper<TPurchaseMallGoodsEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("goods_status", 1);
List<TPurchaseMallGoodsEntity> esProductList = tPurchaseMallGoodsService.list(queryWrapper);
//设置商品来源 单独商品
esProductList.stream().forEach(p -> {
p.setGoodsFromFlag(1);
p.setGoodsFromFlag2GroupId(null);
});
rs = esUtils.bulkAdd(elasticsearchIndexName, esProductList);
} catch (IOException e) {
e.printStackTrace();
}
// Iterable<TPurchaseMallGoodsEntity> esProductIterable = productRepository.saveAll(esProductList);
// Iterator<TPurchaseMallGoodsEntity> iterator = esProductIterable.iterator();
// int result = 0;
// while (iterator.hasNext()) {
// result++;
// iterator.next();
// }
return rs;
}
@Override
public Boolean delete(String id) {
Boolean rs = false;
try {
rs = esUtils.deleteDoc(elasticsearchIndexName, id);
} catch (IOException e) {
e.printStackTrace();
}
// productRepository.deleteById(id);
return rs;
}
@Override
public Boolean create(String id) {
Boolean rs = false;
TPurchaseMallGoodsEntity result = null;
TPurchaseMallGoodsEntity esProduct = tPurchaseMallGoodsService.getById(id);
esProduct.setGoodsFromFlag(1);
esProduct.setGoodsFromFlag2GroupId(null);
// result = productRepository.save(esProduct);
try {
if (esUtils.docExists(elasticsearchIndexName, id)) {
rs = esUtils.updateDoc(elasticsearchIndexName, esProduct.getId(), esProduct);
} else {
rs = esUtils.addDoc(elasticsearchIndexName, esProduct.getId(), esProduct);
}
} catch (IOException e) {
e.printStackTrace();
}
return rs;
}
@Override
public void delete(List<String> ids) {
if (!CollectionUtils.isEmpty(ids)) {
List<TPurchaseMallGoodsEntity> esProductList = new ArrayList<>();
for (String id : ids) {
TPurchaseMallGoodsEntity TPurchaseMallGoodsEntity = new TPurchaseMallGoodsEntity();
TPurchaseMallGoodsEntity.setId(id);
esProductList.add(TPurchaseMallGoodsEntity);
}
productRepository.deleteAll(esProductList);
}
}
@Override
public void deleteAll() {
productRepository.deleteAll();
}
@Override
public Page<TPurchaseMallGoodsEntity> search(String keyWord, Integer pageNum, Integer pageSize) {
Pageable pageable = PageRequest.of(pageNum, pageSize);
return productRepository.findByGoodsName(keyWord, pageable);
}
@Override
public TPurchaseMallGoodsEntity getById(String goodsId) {
TPurchaseMallGoodsEntity goodsEntity = new TPurchaseMallGoodsEntity();
try {
Boolean b = esUtils.docExists(elasticsearchIndexName, goodsId);
if (b) {
GetResponse getResponse = esUtils.getDoc(elasticsearchIndexName, goodsId);
Map<String, Object> r = getResponse.getSource();
goodsEntity = JSON.parseObject(JSON.toJSONString(r), TPurchaseMallGoodsEntity.class);
}
} catch (IOException e) {
e.printStackTrace();
}
return goodsEntity;
}
@Override
public Boolean createGroupGoods(Long goodsRelationId) {
Boolean rs = false;
List<TPurchaseMallGoodsEntity> esProductList = new ArrayList<>();
List<TPurchaseMallGoodsCategoryRelationEntity> esProductCategoryList = new ArrayList<>();
try {
TPurchaseMallGoodsRelationEntity gr = tPurchaseMallGoodsRelationService.getById(goodsRelationId);
String groupName = gr.getGroupName();
String groupSearchTitle = gr.getGroupSearchTitle();
String groupMainGoodsId = gr.getGroupMainGoodsId();
String groupGoodsId = gr.getGroupGoodsId();
String goodsIds = gr.getGoodsIds();
//查询商品组主商品详情
TPurchaseMallGoodsEntity goodsEntityGroupMain = tPurchaseMallGoodsService.getById(groupMainGoodsId);
//查询商品组所有商品分类
List<String> goodsIdsList = Arrays.asList(goodsIds.split(","));
String redisKey_NonPageGoodsCategoryRelation = "BSHC_my_goods_category_relation_goods_id_in_" + goodsIdsList.toString();
QueryWrapper<TPurchaseMallGoodsCategoryRelationEntity> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.in("goods_id", goodsIdsList).groupBy("category_id");
List<TPurchaseMallGoodsCategoryRelationEntity> goodsCategoryRelationEntityList = new ArrayList<>();
if (StringUtils.isNull(redisTemplate.opsForValue().get(redisKey_NonPageGoodsCategoryRelation))) {
goodsCategoryRelationEntityList = tPurchaseMallGoodsCategoryRelationService.list(queryWrapper1);
redisTemplate.opsForValue().set(redisKey_NonPageGoodsCategoryRelation, JSON.toJSON(goodsCategoryRelationEntityList).toString(), 10, TimeUnit.MINUTES);
} else {
goodsCategoryRelationEntityList = JSONObject.parseArray(redisTemplate.opsForValue().get(redisKey_NonPageGoodsCategoryRelation).toString(), TPurchaseMallGoodsCategoryRelationEntity.class);
}
//替换商品组主商品 id goodsName searchTitle
// String goodsIdGroup = IdGen.uuid();
goodsEntityGroupMain.setId(groupGoodsId);
goodsEntityGroupMain.setGoodsName(groupName);
goodsEntityGroupMain.setSearchTitle(groupSearchTitle);
goodsEntityGroupMain.setSpecValue(null);
// goodsEntityGroupMain.setSupplierSalerId(null);
// goodsEntityGroupMain.setSupplierSalerName(null);
//设置商品组主商品 goodsFromFlag goodsFromFlag2GroupId
goodsEntityGroupMain.setGoodsFromFlag(2);
goodsEntityGroupMain.setGoodsFromFlag2GroupId(gr.getId());
esProductList.add(goodsEntityGroupMain);
goodsCategoryRelationEntityList.stream().forEach(gcr -> {
TPurchaseMallGoodsCategoryRelationEntity goodsCategoryRelationEntity = new TPurchaseMallGoodsCategoryRelationEntity();
goodsCategoryRelationEntity.setGoodsId(groupGoodsId);
goodsCategoryRelationEntity.setCategoryId(gcr.getCategoryId());
esProductCategoryList.add(goodsCategoryRelationEntity);
});
rs = esUtils.bulkAdd(elasticsearchIndexName, esProductList);
//保存商品分类
if (rs) {
esProductCategoryList.stream().forEach(epc -> {
//先删除已有的商品分类
QueryWrapper<TPurchaseMallGoodsCategoryRelationEntity> qwRemove = new QueryWrapper<>();
qwRemove.eq("goods_id", epc.getGoodsId()).eq("category_id", epc.getCategoryId());
tPurchaseMallGoodsCategoryRelationService.remove(qwRemove);
//新增新的商品分类
tPurchaseMallGoodsCategoryRelationService.save(epc);
});
}
} catch (IOException e) {
e.printStackTrace();
}
return rs;
}
}