链式数据分析引擎解析
我套了个UI:gitee.com/0X00000000/…
函数入口解析
- 函数调用这里采用了链式写法。
- 但是这个链式前面的都是初始化数据的,最后一步才真正执行!
- 有些链式前面处理数据,接着后面在处理。
数据处理简单流程
/**
*过滤数据
*这里保存结果数据
*key 如果没有group by的时候是空的
* 有group by则为分组的key;如果分组key有转换则进行转化
*注意这里的key只能一个
*/
Map<Object,List<Object>> mapping;
//过滤数据
if(conditionCheckOK(line)){
Object key = null;
if(!StringUtil.isEmpty(groupBy)){
key = atts[groupByIndex];
key = preProcess((String)key,groupByIndex);
}
List<Object> list = mapping.get(key);
if(list == null){
list = new ArrayList<Object>();
}
list.add(line);
mapping.put(key, list);
}
数据如何过滤
- 先过滤数据
- 在取数、有函数转化的进行函数处理(select 1,avg(1) from a group 1)
- 这个函数转换需要注意。举例:平均值(维护总数,和)-》最后得平均值
- 因为式select内容所以这里识别支持的函数也是个难点
- 有分组的按照分组存放数据
- 排序是放在数据最后输出的
- 最后说下这里的处理基本单线程的。
@Test
public void testWhere()throws Exception{
//设置了count这里 这是有函数的类似avg、max、min
scaner.select("count(1)")
//过滤器这里可以用个链式过滤来实现
.where(Conditions.and(Conditions.contains("6", "service/ws/WsService?"),
Conditions.eq("8", "200")))
.orderBy(OrderBy.desc(1))
.list();
scaner.print();
}
@Test
public void testMoreCondition()throws Exception{
scaner.select("0,3,6,8")
//格式化获取到的数据
.processor(3, processor)
.where(Conditions.or(Conditions.eq("8", "404"),Conditions.eq("8", "302")))
.list();
scaner.print();
}
初始化查询字段的解析
- 先切割
- 判断是否有( ->有则对应一个函数 ->提取出来对应的列和函数名
- 分组的列也初始化提取了
private List<SelectedProp> selectedProps = new ArrayList<SelectedProp>();
private void init() throws Exception{
String indexStrs[] = selectedPropsStr.split(",");
for(String indexStr : indexStrs){
Integer index = null;
String function = null;
if(indexStr.contains("(")){
try{
indexStr = indexStr.replaceAll("\\(", " ");
indexStr = indexStr.replaceAll("\\)", " ");
function = indexStr.substring(0,indexStr.indexOf(" "));
indexStr = indexStr.substring(indexStr.indexOf(" ")+1);
indexStr = indexStr.trim();
index = Integer.parseInt(indexStr);
hasFunction = true;
}catch(Exception e){
throw new WrongFormatException("select pattern is invalid:" + selectedPropsStr + ",near '" + indexStr + "'");
}
}else{
try{
index = Integer.parseInt(indexStr);
}catch(Exception e){
throw new WrongFormatException("content select is invalid:" + selectedPropsStr+ ",near '" + indexStr + "'");
}
}
if(index > maxIndex){
maxIndex = index;
}
selectedProps.add(new SelectedProp(index,function));
}
try{
if(!StringUtil.isEmpty(groupBy)){
groupByIndex = Integer.parseInt(groupBy);
}
}catch(Exception e){
throw new WrongFormatException("content select is invalid:" + selectedPropsStr+ ",near '" + groupBy + "'");
}
}
平均数的格式转换
- 接口定义
public interface FunctionExecutor {
final static Logger log = Logger.getLogger(FunctionExecutor.class.getName());
public boolean accumulation(String lineValue);
public Double getResult();
}
- 平均数是实现
- 最后获取函数最终结果
public class AvgFunction implements FunctionExecutor{
double total;
int lineCount;
@Override
public boolean accumulation(String lineValue) {
try{
total+=Double.parseDouble(lineValue);
lineCount++;
}catch(Exception e){
log.log(Level.SEVERE, "数据:"+lineValue, e);
}
return false;
}
@Override
public Double getResult() {
if(lineCount>0){
return NumberUtil.round2Digit((total*1.0)/lineCount);
}
return 0d;
}
}