增加ES搜索服务

商城业务-->商品上架功能
This commit is contained in:
Kirk Lin 2021-06-22 15:59:33 +08:00
parent 119ab6fa81
commit b25c34edb8
27 changed files with 887 additions and 22 deletions

View file

@ -0,0 +1,124 @@
package name.lkk.common.to.es;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
/**
* <p>Title: SkuEsModel</p>
* Description
* "mappings": {
* "properties": {
* "skuId":{
* "type": "long"
* },
* "spuId":{
* "type": "keyword"
* },
* "skuTitle":{
* "type": "text",
* "analyzer": "ik_smart"
* },
* "skuPrice":{
* "type": "keyword"
* },
* "skuImg":{
* "type": "keyword",
* "index": false,
* "doc_values": false
* },
* "saleCount":{
* "type": "long"
* },
* "hasStock":{
* "type": "boolean"
* },
* "hotScore":{
* "type": "long"
* },
* "brandId":{
* "type": "long"
* },
* "catalogId":{
* "type": "long"
* },
* "brandName":{
* "type":"keyword",
* "index": false,
* "doc_values": false
* },
* "brandImg":{
* "type": "keyword",
* "index": false,
* "doc_values": false
* },
* "catalogName":{
* "type": "keyword",
* "index": false,
* "doc_values": false
* },
* "attrs":{
* "type": "nested",
* "properties": {
* "attrId":{
* "type":"long"
* },
* "attrName":{
* "type":"keyword",
* "index":false,
* "doc_values": false
* },
* "attrValue":{
* "type":"keyword"
* }
* }
* }
* }
* }
* date2020/6/8 18:52
*/
@Data
public class SkuEsModel implements Serializable {
private Long skuId;
private Long spuId;
private String skuTitle;
private BigDecimal skuPrice;
private String skuImg;
private Long saleCount;
private Boolean hasStock;
private Long hotScore;
private Long brandId;
private Long catalogId;
private String brandName;
private String brandImg;
private String catalogName;
private List<Attrs> attrs;
/**
* 检索属性
*/
@Data
public static class Attrs implements Serializable{
private Long attrId;
private String attrName;
private String attrValue;
}
}

View file

@ -0,0 +1,16 @@
package name.lkk.common.to.es;
import lombok.Data;
/**
* <p>Title: SkuHasStockVo</p>
* Description存储这个sku是否有库存
* date2020/6/8 20:10
*/
@Data
public class SkuHasStockVo {
private Long skuId;
private Boolean hasStock;
}

View file

@ -34,6 +34,14 @@ public class SpuInfoController {
return R.ok().setData(entity);
}
/**
* 商品上架
*/
@PostMapping("/{spuId}/up")
public R up(@PathVariable("spuId") Long spuId){
spuInfoService.up(spuId);
return R.ok();
}
/**
* spu管理的查询

View file

@ -1,8 +1,9 @@
package name.lkk.kkmall.product.dao;
import name.lkk.kkmall.product.entity.SpuInfoEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import name.lkk.kkmall.product.entity.SpuInfoEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* spu信息
@ -13,5 +14,8 @@ import org.apache.ibatis.annotations.Mapper;
*/
@Mapper
public interface SpuInfoDao extends BaseMapper<SpuInfoEntity> {
/**
* 修改上架成功的商品的状态
*/
void updateSpuStatus(@Param("spuId") Long spuId, @Param("code") int code);
}

View file

@ -9,9 +9,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
/**
* <p>Title: CouponFeignService</p>
* Description远程调用优惠券服务
* date2020/6/5 17:06
* 远程调用优惠券服务
*/
@FeignClient("kkmall-coupon")
public interface CouponFeignService {

View file

@ -0,0 +1,20 @@
package name.lkk.kkmall.product.feign;
import name.lkk.common.to.es.SkuEsModel;
import name.lkk.common.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
/**
* 远程上架商品
*/
@FeignClient("kkmall-search")
public interface SearchFeignService {
@PostMapping("/search/save/product")
R productStatusUp(@RequestBody List<SkuEsModel> skuEsModels);
}

View file

@ -0,0 +1,21 @@
package name.lkk.kkmall.product.feign;
import name.lkk.common.utils.R;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
/**
* 远程调用库存服务
*/
@FeignClient("kkmall-ware")
public interface WareFeignService {
/**
* 修改整个系统的 R 带上泛型
*/
@PostMapping("/ware/waresku/hasStock")
R getSkuHasStock(@RequestBody List<Long> SkuIds);
}

View file

@ -32,5 +32,11 @@ public interface SpuInfoService extends IService<SpuInfoEntity> {
SpuInfoEntity getSpuInfoBySkuId(Long skuId);
void saveSpuInfo(SpuSaveVo vo);
/**
* 商品上架
* @param spuId
*/
void up(Long spuId);
}

View file

@ -1,16 +1,22 @@
package name.lkk.kkmall.product.service.impl;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import name.lkk.common.constant.ProductConstant;
import name.lkk.common.to.SkuReductionTO;
import name.lkk.common.to.SpuBoundTO;
import name.lkk.common.to.es.SkuEsModel;
import name.lkk.common.to.es.SkuHasStockVo;
import name.lkk.common.utils.PageUtils;
import name.lkk.common.utils.Query;
import name.lkk.common.utils.R;
import name.lkk.kkmall.product.dao.SpuInfoDao;
import name.lkk.kkmall.product.entity.*;
import name.lkk.kkmall.product.feign.CouponFeignService;
import name.lkk.kkmall.product.feign.SearchFeignService;
import name.lkk.kkmall.product.feign.WareFeignService;
import name.lkk.kkmall.product.service.*;
import name.lkk.kkmall.product.vo.*;
import org.springframework.beans.BeanUtils;
@ -20,9 +26,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
@ -52,12 +56,27 @@ public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> i
@Autowired
private SkuSaleAttrValueService skuSaleAttrValueService;
@Autowired
private BrandService brandService;
@Autowired
private CategoryService categoryService;
/**
* feign 远程调用优惠券服务
*/
@Autowired
private CouponFeignService couponFeignService;
/**
* feign 远程调用库存服务
*/
@Autowired
private WareFeignService wareFeignService;
/**
* feign 远程调用ES服务
*/
@Autowired
private SearchFeignService searchFeignService;
@Override
public PageUtils queryPage(Map<String, Object> params) {
@ -228,4 +247,82 @@ public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> i
}
}
@Override
public void up(Long spuId) {
// 1 组装数据 查出当前spuId对应的所有sku信息
List<SkuInfoEntity> skus = skuInfoService.getSkusBySpuId(spuId);
// 查询这些sku是否有库存
List<Long> skuids = skus.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
// 2 封装每个sku的信息
// 3.查询当前sku所有可以被用来检索的规格属性
// 获取所有的spu商品的id 然后查询这些id中那些是可以被检索的 [数据库中目前 45611不可检索]
List<ProductAttrValueEntity> baseAttrs = attrValueService.baseAttrListForSpu(spuId);
List<Long> attrIds = baseAttrs.stream().map(ProductAttrValueEntity::getAttrId).collect(Collectors.toList());
// 可检索的id集合
Set<Long> isSet = new HashSet<>(attrService.selectSearchAttrIds(attrIds));
// 根据商品id 过滤不可检索的商品 最后映射号检索属性
List<SkuEsModel.Attrs> attrs = baseAttrs.stream().filter(item -> isSet.contains(item.getAttrId())).map(item -> {
SkuEsModel.Attrs attr = new SkuEsModel.Attrs();
BeanUtils.copyProperties(item, attr);
return attr;
}).collect(Collectors.toList());
// skuId 对应 是否有库存
Map<Long, Boolean> stockMap = null;
try {
// 3.1 发送远程调用 库存系统查询是否有库存
R hasStock = wareFeignService.getSkuHasStock(skuids);
// 构造器受保护 所以写成内部类对象
stockMap = hasStock.getData(new TypeReference<List<SkuHasStockVo>>(){}).stream().collect(Collectors.toMap(SkuHasStockVo::getSkuId, item -> item.getHasStock()));
log.warn("服务调用成功" + hasStock);
} catch (Exception e) {
log.error("库存服务调用失败: 原因{}",e);
}
Map<Long, Boolean> finalStockMap = stockMap;
List<SkuEsModel> collect = skus.stream().map(sku -> {
SkuEsModel esModel = new SkuEsModel();
BeanUtils.copyProperties(sku, esModel);
esModel.setSkuPrice(sku.getPrice());
esModel.setSkuImg(sku.getSkuDefaultImg());
// 4 设置库存
if(finalStockMap == null){
esModel.setHasStock(true);
}else {
esModel.setHasStock(finalStockMap.get(sku.getSkuId()));
}
// TODO 1.热度评分 0
esModel.setHotScore(0L);
BrandEntity brandEntity = brandService.getById(esModel.getBrandId());
// brandNamebrandImg
esModel.setBrandName(brandEntity.getName());
esModel.setBrandImg(brandEntity.getLogo());
// 查询分类信息
CategoryEntity categoryEntity = categoryService.getById(esModel.getCatalogId());
esModel.setCatalogName(categoryEntity.getName());
// 保存商品的属性
esModel.setAttrs(attrs);
return esModel;
}).collect(Collectors.toList());
// 5.发给ES进行保存 mall-search
R r = searchFeignService.productStatusUp(collect);
if(r.getCode() == 0){
// 远程调用成功
baseMapper.updateSpuStatus(spuId, ProductConstant.StatusEnum.SPU_UP.getCode());
}else{
// 远程调用失败 TODO 接口幂等性 重试机制
/**
* Feign 的调用流程 Feign有自动重试机制
*/
}
}
}

View file

@ -15,6 +15,9 @@
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
</resultMap>
<update id="updateSpuStatus">
UPDATE `pms_spu_info` SET publish_status = #{code}, update_time = NOW() WHERE id = #{spuId}
</update>
</mapper>

83
kkmall-search/pom.xml Normal file
View file

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.kirklin.kkmall</groupId>
<artifactId>kkmall-search</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>kkmall-search</name>
<description>Demo project for Spring Boot</description>
<properties>
<spring-cloud.version>2020.0.3</spring-cloud.version>
<elasticsearch.version>7.13.2</elasticsearch.version>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>name.lkk.kkmall</groupId>
<artifactId>kkmall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<!-- 排除 Mybatis-Plus -->
<exclusion>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,15 @@
package cn.kirklin.kkmall.search;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication
public class KkmallSearchApplication {
public static void main(String[] args) {
SpringApplication.run(KkmallSearchApplication.class, args);
}
}

View file

@ -0,0 +1,29 @@
package cn.kirklin.kkmall.search.bean;
import lombok.Data;
@Data
public class Account {
private int accountNumber;
private int balance;
private String firstname;
private String lastname;
private int age;
private String gender;
private String address;
private String employer;
private String email;
private String city;
private String state;
}

View file

@ -0,0 +1,12 @@
package cn.kirklin.kkmall.search.bean;
import lombok.Data;
@Data
public class User {
private String userName;
private String gender;
private String age;
}

View file

@ -0,0 +1,37 @@
package cn.kirklin.kkmall.search.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author: kirklin
* @date: 2021/6/21 9:59 下午
* @description:
*/
@Configuration
public class MallElasticSearchConfig {
public static final RequestOptions COMMON_OPTIONS;
static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
// builder.addHeader("Authorization", "Bearer " + TOKEN);
// builder.setHttpAsyncResponseConsumerFactory(
// new HttpAsyncResponseConsumerFactory
// .HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
COMMON_OPTIONS = builder.build();
}
@Bean
public RestHighLevelClient esRestClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")));
return client;
}
}

View file

@ -0,0 +1,18 @@
package cn.kirklin.kkmall.search.constant;
/**
* ES常量
* @author kirklin
*/
public class EsConstant {
/**
* sku数据在ES中的索引
*/
public static final String PRODUCT_INDEX = "product";
/**
* 分页的大小
*/
public static final int PRODUCT_PAGE_SIZE = 2;
}

View file

@ -0,0 +1,52 @@
package cn.kirklin.kkmall.search.controller;
/**
* @author: kirklin
* @date: 2021/6/22 3:42 下午
* @description:
*/
import cn.kirklin.kkmall.search.service.ProductSaveService;
import lombok.extern.slf4j.Slf4j;
import name.lkk.common.exception.BizCodeEnum;
import name.lkk.common.to.es.SkuEsModel;
import name.lkk.common.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.util.List;
/**
* 商品上架
*/
@Slf4j
@RequestMapping("/search/save")
@RestController
public class ElasticSaveController {
@Autowired
private ProductSaveService productSaveService;
/**
* 上架商品
*/
@PostMapping("/product")
public R productStatusUp(@RequestBody List<SkuEsModel> skuEsModels){
boolean status;
try {
status = productSaveService.productStatusUp(skuEsModels);
} catch (IOException e) {
log.error("ElasticSaveController商品上架错误: {}", e);
return R.error(BizCodeEnum.PRODUCT_UP_EXCEPTION.getCode(), BizCodeEnum.PRODUCT_UP_EXCEPTION.getMsg());
}
if(!status){
return R.ok();
}
return R.error(BizCodeEnum.PRODUCT_UP_EXCEPTION.getCode(), BizCodeEnum.PRODUCT_UP_EXCEPTION.getMsg());
}
}

View file

@ -0,0 +1,17 @@
package cn.kirklin.kkmall.search.service;
import name.lkk.common.to.es.SkuEsModel;
import java.io.IOException;
import java.util.List;
/**
* @author: kirklin
* @date: 2021/6/22 3:43 下午
* @description:
*/
public interface ProductSaveService {
boolean productStatusUp(List<SkuEsModel> skuEsModels) throws IOException;
}

View file

@ -0,0 +1,57 @@
package cn.kirklin.kkmall.search.service.impl;
import cn.kirklin.kkmall.search.config.MallElasticSearchConfig;
import cn.kirklin.kkmall.search.constant.EsConstant;
import cn.kirklin.kkmall.search.service.ProductSaveService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import name.lkk.common.to.es.SkuEsModel;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
public class ProductSaveServiceImpl implements ProductSaveService {
@Resource
private RestHighLevelClient client;
/**
* 将数据保存到ES
* BulkRequest bulkRequest, RequestOptions options
*/
@Override
public boolean productStatusUp(List<SkuEsModel> skuEsModels) throws IOException {
// 1.给ES建立一个索引 product
BulkRequest bulkRequest = new BulkRequest();
// 2.构造保存请求
for (SkuEsModel esModel : skuEsModels) {
IndexRequest indexRequest = new IndexRequest(EsConstant.PRODUCT_INDEX);
// 设置索引id
indexRequest.id(esModel.getSkuId().toString());
String jsonString = JSON.toJSONString(esModel);
indexRequest.source(jsonString, XContentType.JSON);
bulkRequest.add(indexRequest);
}
BulkResponse bulk = client.bulk(bulkRequest, MallElasticSearchConfig.COMMON_OPTIONS);
// TODO 是否拥有错误
boolean hasFailures = bulk.hasFailures();
if(hasFailures){
List<String> collect = Arrays.stream(bulk.getItems()).map(BulkItemResponse::getId).collect(Collectors.toList());
log.error("商品上架错误:{}",collect);
}
return hasFailures;
}
}

View file

@ -0,0 +1,71 @@
PUT product
{
"mappings": {
"properties": {
"skuId":{
"type": "long"
},
"spuId":{
"type": "keyword"
},
"skuTitle":{
"type": "text",
"analyzer": "ik_smart"
},
"skuPrice":{
"type": "keyword"
},
"skuImg":{
"type": "keyword",
"index": false,
"doc_values": false
},
"saleCount":{
"type": "long"
},
"hasStock":{
"type": "boolean"
},
"hotScore":{
"type": "long"
},
"brandId":{
"type": "long"
},
"catalogId":{
"type": "long"
},
"brandName":{
"type":"keyword",
"index": false,
"doc_values": false
},
"brandImg":{
"type": "keyword",
"index": false,
"doc_values": false
},
"catalogName":{
"type": "keyword",
"index": false,
"doc_values": false
},
"attrs":{
"type": "nested",
"properties": {
"attrId":{
"type":"long"
},
"attrName":{
"type":"keyword",
"index":false,
"doc_values": false
},
"attrValue":{
"type":"keyword"
}
}
}
}
}
}

View file

@ -0,0 +1,9 @@
server:
port: 12000
spring:
application:
name: kkmall-search
cloud:
nacos:
discovery:
server-addr: localhost:8848

View file

@ -0,0 +1,128 @@
package cn.kirklin.kkmall.search;
import cn.kirklin.kkmall.search.bean.Account;
import cn.kirklin.kkmall.search.bean.User;
import cn.kirklin.kkmall.search.config.MallElasticSearchConfig;
import com.alibaba.fastjson.JSON;
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.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.Avg;
import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
@SpringBootTest
class KkmallSearchApplicationTests {
@Autowired
RestHighLevelClient client;
@Test
@DisplayName("测试RestHighLevelClient是否存在")
void contextLoads() {
System.out.println(client);
}
/**
* 检索数据
*/
@Test
@DisplayName("测试ES检索数据")
public void searchDataTest() throws IOException {
SearchRequest searchRequest = new SearchRequest();
// 指定索引
searchRequest.indices("bank");
// 1.指定检索条件 DSL
SearchSourceBuilder builder = new SearchSourceBuilder();
// 1.1 构造检索条件
builder.query(QueryBuilders.matchQuery("address","mill"));
// 1.2 按照年龄值聚合
TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(10);
builder.aggregation(ageAgg);
// 1.3 计算平均薪资
AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("balanceAvg").field("balance");
builder.aggregation(balanceAvg);
System.out.println("检索条件:" + builder);
searchRequest.source(builder);
// 2.执行检索
SearchResponse search = client.search(searchRequest, MallElasticSearchConfig.COMMON_OPTIONS);
// 3.分析结果
// Map map = JSON.parseObject(search.toString(), Map.class);
// System.out.println(map);
// 3.1 索取所有记录
SearchHits hits = search.getHits();
// 详细记录
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
// String index = hit.getIndex();
// String id = hit.getId();
String source = hit.getSourceAsString();
Account account = JSON.parseObject(source, Account.class);
System.out.println(account);
}
// 获取分析数据
Aggregations aggregations = search.getAggregations();
// List<Aggregation> list = aggregations.asList();
// for (Aggregation aggregation : list) {
// Terms agg = aggregations.get(aggregation.getName());
// System.out.println(agg.getBuckets());
// }
Terms agg = aggregations.get("ageAgg");
for (Terms.Bucket bucket : agg.getBuckets()) {
System.out.println("年龄: " + bucket.getKeyAsString() + "-->" + bucket.getDocCount() + "");
}
Avg avg = aggregations.get("balanceAvg");
System.out.println("平均薪资: " + avg.getValue());
}
/**
* 插入数据
*/
@Test
@DisplayName("测试ES插入数据")
public void indexTest() throws IOException {
IndexRequest request = new IndexRequest("users");
// 设置索引id
request.id("2");
// 第1种方式
// request.source("userName","firenay","age","20","gender","");
// 第2种方式
User user = new User();
user.setUserName("kk");
user.setAge("20");
user.setGender("");
String jsonString = JSON.toJSONString(user);
// 传入json时 指定类型
request.source(jsonString, XContentType.JSON);
// 执行保存操作
IndexResponse response = client.index(request, MallElasticSearchConfig.COMMON_OPTIONS);
System.out.println(response);
System.out.println(response.status());
}
}

View file

@ -1,19 +1,16 @@
package name.lkk.kkmall.ware.controller;
import java.util.Arrays;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import name.lkk.kkmall.ware.entity.WareSkuEntity;
import name.lkk.kkmall.ware.service.WareSkuService;
import name.lkk.common.to.es.SkuHasStockVo;
import name.lkk.common.utils.PageUtils;
import name.lkk.common.utils.R;
import name.lkk.kkmall.ware.entity.WareSkuEntity;
import name.lkk.kkmall.ware.service.WareSkuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@ -29,7 +26,15 @@ import name.lkk.common.utils.R;
public class WareSkuController {
@Autowired
private WareSkuService wareSkuService;
/**
* 查询sku是否有库存
* 返回当前id stock量
*/
@PostMapping("/hasStock")
public R getSkuHasStock(@RequestBody List<Long> skuIds){
List<SkuHasStockVo> vos = wareSkuService.getSkuHasStock(skuIds);
return R.ok().setData(vos);
}
/**
* 列表
*/

View file

@ -17,4 +17,10 @@ public interface WareSkuDao extends BaseMapper<WareSkuEntity> {
void addStock(@Param("skuId") Long skuId, @Param("wareId") Long wareId, @Param("skuNum") Integer skuNum);
/**
* 查询是否有库存
* @param id
* @return
*/
Long getSkuStock(Long id);
}

View file

@ -1,9 +1,11 @@
package name.lkk.kkmall.ware.service;
import com.baomidou.mybatisplus.extension.service.IService;
import name.lkk.common.to.es.SkuHasStockVo;
import name.lkk.common.utils.PageUtils;
import name.lkk.kkmall.ware.entity.WareSkuEntity;
import java.util.List;
import java.util.Map;
/**
@ -22,5 +24,11 @@ public interface WareSkuService extends IService<WareSkuEntity> {
*/
double addStock(Long skuId, Long wareId, Integer skuNum);
/**
* 查询sku是否有库存
* @param skuIds
* @return
*/
List<SkuHasStockVo> getSkuHasStock(List<Long> skuIds);
}

View file

@ -3,6 +3,7 @@ package name.lkk.kkmall.ware.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import name.lkk.common.to.es.SkuHasStockVo;
import name.lkk.common.utils.PageUtils;
import name.lkk.common.utils.Query;
import name.lkk.common.utils.R;
@ -17,6 +18,7 @@ import org.springframework.util.ObjectUtils;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service("wareSkuService")
@ -87,5 +89,21 @@ public class WareSkuServiceImpl extends ServiceImpl<WareSkuDao, WareSkuEntity> i
return price;
}
/**
* 这里存过库存数量
* SELECT SUM(stock - stock_locked) FROM `wms_ware_sku` WHERE sku_id = 1
*/
@Override
public List<SkuHasStockVo> getSkuHasStock(List<Long> skuIds) {
return skuIds.stream().map(id -> {
SkuHasStockVo stockVo = new SkuHasStockVo();
// 查询当前sku的总库存量
stockVo.setSkuId(id);
// 这里库存可能为null 要避免空指针异常
stockVo.setHasStock(baseMapper.getSkuStock(id)==null?false:true);
return stockVo;
}).collect(Collectors.toList());
}
}

View file

@ -16,5 +16,8 @@
<insert id="addStock">
UPDATE `wms_ware_sku` SET stock = stock + #{skuNum} WHERE sku_id = #{skuId} AND ware_id = #{wareId}
</insert>
<select id="getSkuStock" resultType="java.lang.Long">
SELECT SUM(stock - stock_locked) FROM `wms_ware_sku` WHERE sku_id = #{id}
</select>
</mapper>