查询结果过滤后补全数据
查询结果过滤后补全数据
最近在对接京东商品, 需要勾选只显示有货条件进行筛选, 众所周知的一个问题是京东是在各个地区有独立的仓储, 而有些货物并不是在所有仓库中都有备货的,比如咱们国家的钓鱼岛!
难点
在设计过程中需要考虑一下几个难点
- 比如查询第一页数据是10条,而查询出10条数据后, 通过调用京东接口发现有3条数据是无货数据, 这个时候如果从第二页中拿取数据,不确定需要拿多少才能补全这三条数据,因为新获取的数据中同样可能存在无库存数据
- 比如用在获取第十页数据时,前九页数据中不知道存在多少条无货数据,需要将这些数据过滤掉, 然后才能获取到最新的不重复的第十页数据.
方案
经过多个构思方案的对比, 从调用次数, 循环操作及性能等多方面考虑后最终采用以下方案进行处理
- 每次从数据库中获取100条数据, (设定为获取100条数据是因为性能上与获取10条数据查询效率基本一样,另一个问题是京东接口单次调用最多只支持100个sku合并查询, 查询数据超过一百条时查询需要拆分多次调用京东接口,而除极限情况外,查询一页数据时, 基本不需要多次调用京东接口,减少查询次数)
- 将从京东查询到的无货的数据进行计数noGoodsCount, 并返回给前端, 当前端查询下一页数据时,会再传递给后端,这样就可以计算出此次查询需要从第几条数据开始查询(offset+noGoodsCount),而每次处理完返回结果时需要加上新增的无货数据
注意: 此处查询京东数据用到的是京东sku, 而一个商品对应多个sku,因此需要处理两个问题- 当sku数量超过100时需要分页循环查询京东接口
- 当一个spu中同时存在有货与无货数据时,noGoodsCount中不做计数.
代码实例
private void screenProductList(
Integer extendSize = 100-pageBean.getPageSize();
final Integer noGoodsCount = productSearchBean.getNoGoodsCount();
Integer noGoodsNum = productSearchBean.getNoGoodsCount();
String[] adress = productSearchBean.getArea().split("_");
String area = null;
if(adress.length >= 3){
ConsigneeAdress address = new ConsigneeAdress();
address.setProvinceid(Long.parseLong(adress[0]));
address.setCityid(Long.parseLong(adress[1]));
address.setDistrictid(Long.parseLong(adress[2]));
JDAddress jdAddress = districtInfoService.getJdAddress(address);
area = jdAddress.getProvinceId()+"_"+jdAddress.getCityId()+"_"+jdAddress.getCountyId();
}
int flog = -1;
for (int i = 0; i < 5; i++) {//查询最大500条数据,若仍我数据则直接返回提示--查询超时
productSearchBean.setNoGoodsCount(noGoodsCount + (extendSize+pageBean.getPageSize()) * i);
productSearchBean.setExtendSize(extendSize);
List<ProductEntity> entitys = productMapper.getProductsByPage(productSearchBean, pageBean);
if (entitys == null || entitys.size() == 0){
break;
}
JSONObject json = this.screenProductList(entitys, pageBean.getPageSize()-list.size(), area);
if (json != null){
entitys = (List<ProductEntity>)json.get("list");
list.addAll(entitys);
noGoodsNum += json.getInteger("noGoodsCount");
if (list.size() >= pageBean.getPageSize()){
break;
}
}
flog = i;
}
if (flog == 4 && list.size() == 0){
throw new BusinessException("您的地址信息太过偏远。请查看全部商品");
}
pageResultBean.setReserve(noGoodsNum.toString());
}
private JSONObject screenProductList(List<ProductEntity> list, Integer pageSize, String area){
JSONObject json = new JSONObject();
Integer noGoodsCount = 0;
List<Long> spuCodes = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
ProductEntity productEntity = list.get(i);
if (productEntity.getSupplierId().equals(jdSeller.getId())){
spuCodes.add(productEntity.getSpuCode());
}
if(pageSize == i && spuCodes.size() == 0){
json.put("list", list.subList(0, pageSize));
json.put("noGoodsCount", noGoodsCount);
return json;
}
}
if(spuCodes.size() == 0){
json.put("list", list);
json.put("noGoodsCount", noGoodsCount);
return json;
}
Map<String, Object> params = new HashMap<>();
params.put("spuCodes", spuCodes);
params.put("supplierId", jdSeller.getId());
List<SkuEntity> skus = skuMapper.selectSkuBySpuCode(params);
List<JDSSkuNums> jdsSkuNumsList = new ArrayList<>();
Map<String, Long> map = new HashMap<>();
for (SkuEntity skuEntity : skus) {
JDSSkuNums jdsSkuNums = new JDSSkuNums();
jdsSkuNums.setNum(1);
jdsSkuNums.setSkuId(skuEntity.getSkuCode());
jdsSkuNumsList.add(jdsSkuNums);
map.put(skuEntity.getSkuCode(), skuEntity.getSpuCode());
}
List<JDNewStock> stocks = new ArrayList<>();
try {
int size = 100;
int page = (jdsSkuNumsList.size() - 1) / size + 1;
for (int i = 1; i <= page; i++) {
int fromIndex = (i-1)*100;
if (i == page){
stocks.addAll(ijdStockService.newStock(jdsSkuNumsList.subList(fromIndex, jdsSkuNumsList.size()), area));
}else{
stocks.addAll(ijdStockService.newStock(jdsSkuNumsList.subList(fromIndex, fromIndex+size), area));
}
}
} catch (Exception e) {
e.printStackTrace();
}
Set<Integer> stockStateSet = ImmutableSet.of(33,39,40);//有货状态编号
Set<Long> set = new HashSet<>();
for (JDNewStock stock : stocks) {
if (stockStateSet.contains(stock.getStockStateId())){
set.add(map.get(stock.getSkuId().toString()));
}
}
List<ProductEntity> entityList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
ProductEntity productEntity = list.get(i);
if (productEntity.getSupplierId().equals(jdSeller.getId()) && !set.contains(productEntity.getSpuCode())){
noGoodsCount ++;
continue;
}
entityList.add(productEntity);
if (pageSize == entityList.size()){
break;
}
}
json.put("list", entityList);
json.put("noGoodsCount", noGoodsCount);
return json;
}
(如果有更好的方法欢迎相互交流)