搜索过滤树结构

搜索过滤树结构

基本思路:

  1. 搜索过滤一般是多字段查询过滤,先利用wrapper获取查询到的所有叶子节点

    • 搜索一般为名称模糊查询
    • 过滤有可能单选、多选和区间过滤
    • 故所搜过滤一般wrapper包装类查询,即QueryWrapper
    • 可利用wrapper中的四种查询语句以满足搜索过滤的需求:like(模糊查询)、eq(等于)、in(在...之内)、between(区间查询)
  2. 再利用叶子节点获取树结构

    • 例用递归查询出所有的节点(从叶子节点一直递归到根节点),保留所有节点id,idSet
    • 查询出所有根节点,保留所有根节点整条信息,并保留根节点之间的顺序(顺序也是树结构的一部分),rootList
  3. 构建搜索过滤树的层级结构

    • 从查询出的根节点出发,rootList走foreach循环每一个根节点
      • 首先获取根节点的子,再与idSet求交,交集即为所求树中实际的子,求交时要注意取子的交,因为子中保留了顺序,顺序也是树结构的一部分
      • 再对每一个子递归,一直到无子的叶子节点
    //搜索过滤树结构
    	    public List<T> getWrapper(Map<String, Object> param) {
    		QueryWrapper<T> wrapper = new QueryWrapper<>();
    		String key = "name";
    		String value = StringKit.of(param.get(key));
    		if (!value.isEmpty()) {
    			wrapper.like("name", value);//like条件
    		}
    
    		key = "test_id";
    		value = StringKit.of(param.get(key));
    		if (value.isEmpty()) {
    			return null;
    		}
    		wrapper.eq(key, where);//eq条件
    		
    		key = "result";
    		if (param.containsKey(key)) {
    			value = StringKit.of(param.get(key));
    			if (value.isEmpty()) {
    				return null;
    			}
    			String[] resultArray = where.split(",");
    			List<Object> resultList = new ArrayList<>();
    			for (String re : resultArray) {
    				if (StringKit.notEmpty(re)) {
    					resultList.add(StringKit.of(re));
    				}
    			}
    			if (resultList.isEmpty()) {
    				return null;
    			}
    			wrapper.in(key, resultList);//in条件
    		}
    		wrapper.eq("dir", false);//加上非文件夹条件
        //获取wrapper查询出的叶子节点
    		List<T> tList = mapper.selectList(wrapper);
        //准备idSet,用于存放所有的节点id
    		Set<Long> idSet = new HashSet<>();
        //准备rootList,用于存方法根节点
    		List<T> rootList = new ArrayList<>();
        //先判断查询出的叶子列表是否为空
    		if(tList.size() == 0) {
    			return new ArrayList<>();
    		}else {
                //把叶子节点id加入idSet
    			tList.forEach(t -> idSet.add(t.getId()));
                //把叶子节点的所有父节点加入idSet,把根节点加入根集合
    			tList.forEach(t -> getParentIdsById(t,idSet,rootList));
                //对根集合每个元素插入与idSet中相交的子
    			rootList.forEach(r -> setChildrenByIdSet(r,idSet));
    			return rootList;
    		}
    	}
    	//递归,获取获取所有父节点id的set集合,并且获取根节点的list集合
    	private void getParentIdsById(T t,Set<Long> idSet,List<T> rootList){
    		Long parentId = t.getParent_id(); 
        //根节点加入根集合
    		if(parentId == 0L) {
                //根集合为了保证顺序故使用list,故应加去重判断
    			if(!rootList.contains(t))
    				rootList.add(t);
    		}else {
                //非根节点的id加入idSet
    			T parent = getById(parentId);
    			if(parent != null) {
    				idSet.add(parentId);
                    //递归
    				getParentIdsById(parent,idSet,rootList);
    			}
    		}
    	}
    	//递归,把idSet与childrenIdList的交集设置为parent的子
    	private void setChildrenByIdSet(T parent,Set<Long> idSet) {
            //获取子节点id的集合
    		List<Long> childrenIdList = mapper.selectIdsByParent(parent.getId());
            //此为递归判断条件
    		if(childrenIdList.size() > 0) {
                //取交,带有顺序的list放前面,取交后的集合也保持顺序
    			childrenIdList.retainAll(idSet);
                //对交集实例化
    			List<T> children = mapper.selectBatchIds(childrenIdList);
                //递归子节点
    			children.forEach(c -> setChildrenByIdSet(c,idSet));
                //设值为子
    			parent.set_children(children);
    		}
    	}
    
    
posted @ 2021-01-05 14:28  来一杯coffee  阅读(431)  评论(0)    收藏  举报