作为电商网站,必然要有商品类目表,以便商品分类检索。而设计商品类目表,又是一件特别繁杂的事情。一件商品可能有多个类目来检索出来,比如苹果手机,可以从品牌检索也可以从手机检索。一个类目对应多个商品,比如手机下对应了多款属于手机类的商品。而类目是一个多叉树结构,类似于文件夹的结构。通常大电商都是把类目整理好了放在cache上,就不用频繁访问数据库和整理排序了。
参考了一下网上无限级分类的表设计,简化模型为一个表内存在父子级从属关系。
表设计好了之后,就需要查询数据并且整理出他们的从属关系。为了减少数据库的查询次数,我采用了全部查询,在内存中生成多叉树的形式。节点类的定义想法非常直接,它存在唯一识别:id,真实信息:name,以及它的子树:ListorMap。
/**树型存储*/classCategoryTree{privatelongid;privateStringname;privateList
使用map生成的话,仅在生成这个过程,就可以把问题化简成n的复杂度。因为Map“知道”自己存储的对象的id,而List要通过遍历才知道它的自己存的元素的id。
另外,遍历源数据的时候,把抽掉的节点remove掉也是一种减少重复遍历的方式。
最后生成的结果如同预期。
对于表设计和这个问题的解决不知道有没有更加规范一点的方式,还需要继续探讨。对于我们项目来说,这个方法已经可以适应了,商品分类我打算用个分类表来做映射,类目表叶子节点的id和商品的id存入,检索的时候根据叶子节点id检索所有商品。本次问题,在于对乱序数组转化为多叉树的模型建立,解决了这个问题,对转化思维又有了进一步的提高。(在这里其实问题的阶并不重要,因为这是有穷集合,类目表的条目基本不会超过几百,考虑的最多的就是访问量的问题,因为小电商不会做cache,每一次访问都生成三级树,所以本次问题重在如何用更好的运算模型去解决同一个问题)
关于三级关系树的运用,我做了一个小的地域管理页面,与类目树是一样的结构。
查询用的sql语句使用in来构造。页面控制使用一级当前id和二级当前id作为请求参数刷新页面。
action的设计也是一般操作数据库的形式,不过列表作为页面展示,而其他作为REST接口。
publicListfindByParent(longparent){returnmysql.queryListSql(model,"whereparent="+parent);}publicListfindByParentList(Listlist){StringBuildersb=newStringBuilder();sb.append("whereparentin(");sb.append(list.get(0).getId());for(inti=1;i