查询结果过滤后补全数据

查询结果过滤后补全数据

查询结果过滤后补全数据

最近在对接京东商品, 需要勾选只显示有货条件进行筛选, 众所周知的一个问题是京东是在各个地区有独立的仓储, 而有些货物并不是在所有仓库中都有备货的,比如咱们国家的钓鱼岛!

难点

在设计过程中需要考虑一下几个难点

  1. 比如查询第一页数据是10条,而查询出10条数据后, 通过调用京东接口发现有3条数据是无货数据, 这个时候如果从第二页中拿取数据,不确定需要拿多少才能补全这三条数据,因为新获取的数据中同样可能存在无库存数据
  2. 比如用在获取第十页数据时,前九页数据中不知道存在多少条无货数据,需要将这些数据过滤掉, 然后才能获取到最新的不重复的第十页数据.

方案

经过多个构思方案的对比, 从调用次数, 循环操作及性能等多方面考虑后最终采用以下方案进行处理

  1. 每次从数据库中获取100条数据, (设定为获取100条数据是因为性能上与获取10条数据查询效率基本一样,另一个问题是京东接口单次调用最多只支持100个sku合并查询, 查询数据超过一百条时查询需要拆分多次调用京东接口,而除极限情况外,查询一页数据时, 基本不需要多次调用京东接口,减少查询次数)
  2. 将从京东查询到的无货的数据进行计数noGoodsCount, 并返回给前端, 当前端查询下一页数据时,会再传递给后端,这样就可以计算出此次查询需要从第几条数据开始查询(offset+noGoodsCount),而每次处理完返回结果时需要加上新增的无货数据
    注意: 此处查询京东数据用到的是京东sku, 而一个商品对应多个sku,因此需要处理两个问题
    1. 当sku数量超过100时需要分页循环查询京东接口
    2. 当一个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;
}

(如果有更好的方法欢迎相互交流)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值