Files
influxdb-springboot-starter/src/main/java/com/njcn/influx/query/InfluxQueryWrapper.java
2023-04-25 10:23:43 +08:00

729 lines
23 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.njcn.influx.query;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import com.njcn.influx.constant.InfluxDbSqlConstant;
import lombok.Data;
import org.influxdb.annotation.Column;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* @author hongawen
* @version 1.0.0
*/
@Data
public class InfluxQueryWrapper {
/***
* 组装后的查询语句
*/
private final StringBuilder sqlSelect = new StringBuilder();
/***
* 需要返回的字段
*/
private final List<String> selectColumns = new ArrayList<>();
/***
* 查询条件字段
*/
private final List<String> conditions = new ArrayList<>();
/***
* 分组集合
*/
private final List<String> groupColumn = new ArrayList<>();
/***
* 排序集合
*/
private final List<String> orderColumn = new ArrayList<>();
/***
* 查询目标表
*/
private Class measurement;
/***
* 返回映射实体
*/
private Class resultEntity;
/***
* 返回和查询用的同一个实体
* @param measurement 查询目标表
*/
public InfluxQueryWrapper(Class measurement) {
this.measurement = measurement;
this.resultEntity = measurement;
this.initSql();
}
/***
* 返回和查询用的不是同一个实体
* @param measurement 查询目标表
* @param resultEntity 返回映射实体
*/
public InfluxQueryWrapper(Class measurement, Class resultEntity) {
this.measurement = measurement;
this.resultEntity = resultEntity;
this.initSql();
}
/***
* 初始化查询语句:'select '
*/
private void initSql() {
this.selectColumns.clear();
this.conditions.clear();
}
/***
* 查询的结果属性
* @author hongawen
* @param fieldsStr 属性值
* 输出为 select ["influxColumn" as fieldStr]的形式
*/
public InfluxQueryWrapper select(String... fieldsStr) {
if (ArrayUtil.isNotEmpty(fieldsStr)) {
StringBuilder selectFragment = new StringBuilder();
Arrays.stream(fieldsStr).forEach(fieldStr -> {
Field field = this.getTargetClassField(resultEntity, fieldStr);
selectFragment.setLength(0);
selectFragment.append(StrPool.C_SPACE)
.append(this.getColumnName(field, fieldStr))
.append(StrPool.C_SPACE)
.append(InfluxDbSqlConstant.AS)
.append(StrPool.C_SPACE)
.append(fieldStr)
.append(StrPool.C_SPACE);
selectColumns.add(selectFragment.toString());
});
}
return this;
}
/************常见的简单函数处理比如max/min/mean/percentile****************/
/***
*
* @author hongawen
* @param functionName 指定函数 max min mean等
* @param columnName 表字段名
* @param resultName 映射名
* @return InfluxQueryWrapper
*/
public InfluxQueryWrapper functionByCustom(String functionName, String columnName, String resultName) {
return this;
}
/***
* 统计记录数
* @author hongawen
* @param columnName 表字段名
* @return InfluxQueryWrapper
* 输出COUNT("columnName")
*/
public InfluxQueryWrapper count(String columnName) {
String selectFragment = InfluxDbSqlConstant.COUNT +
InfluxDbSqlConstant.LBK +
InfluxDbSqlConstant.DQM +
columnName +
InfluxDbSqlConstant.DQM +
InfluxDbSqlConstant.RBK +
InfluxDbSqlConstant.AS_VALUE;
selectColumns.add(selectFragment);
return this;
}
/***
* 统计平均值
* @author hongawen
* @param columnName 表字段名
* @return InfluxQueryWrapper
* 输出MEAN("columnName")
*/
public InfluxQueryWrapper mean(String columnName) {
String selectFragment = InfluxDbSqlConstant.AVG +
InfluxDbSqlConstant.LBK +
InfluxDbSqlConstant.DQM +
columnName +
InfluxDbSqlConstant.DQM +
InfluxDbSqlConstant.RBK +
InfluxDbSqlConstant.AS_VALUE;
selectColumns.add(selectFragment);
return this;
}
/***
* 统计中位数
* @author hongawen
* @param columnName 表字段名
* @return InfluxQueryWrapper
* 输出MEDIAN("columnName")
*/
public InfluxQueryWrapper median(String columnName) {
String selectFragment = InfluxDbSqlConstant.MEDIAN +
InfluxDbSqlConstant.LBK +
InfluxDbSqlConstant.DQM +
columnName +
InfluxDbSqlConstant.DQM +
InfluxDbSqlConstant.RBK +
InfluxDbSqlConstant.AS_VALUE;
selectColumns.add(selectFragment);
return this;
}
/***
* 统计指定字段的最常出现的值
* @author hongawen
* @param columnName 表字段名
* @return InfluxQueryWrapper
* 输出MODE("columnName")
*/
public InfluxQueryWrapper mode(String columnName) {
String selectFragment = InfluxDbSqlConstant.MODE +
InfluxDbSqlConstant.LBK +
InfluxDbSqlConstant.DQM +
columnName +
InfluxDbSqlConstant.DQM +
InfluxDbSqlConstant.RBK +
InfluxDbSqlConstant.AS_VALUE;
selectColumns.add(selectFragment);
return this;
}
/***
* 统计指定字段最大值和最小值的差
* @author hongawen
* @param columnName 表字段名
* @return InfluxQueryWrapper
* 输出SPREAD("columnName")
*/
public InfluxQueryWrapper spread(String columnName) {
String selectFragment = InfluxDbSqlConstant.SPREAD +
InfluxDbSqlConstant.LBK +
InfluxDbSqlConstant.DQM +
columnName +
InfluxDbSqlConstant.DQM +
InfluxDbSqlConstant.RBK +
InfluxDbSqlConstant.AS_VALUE;
selectColumns.add(selectFragment);
return this;
}
/***
* 统计指定字段值求和
* @author hongawen
* @param columnName 表字段名
* @return InfluxQueryWrapper
* 输出SUM("columnName")
*/
public InfluxQueryWrapper sum(String columnName) {
String selectFragment = InfluxDbSqlConstant.SUM +
InfluxDbSqlConstant.LBK +
InfluxDbSqlConstant.DQM +
columnName +
InfluxDbSqlConstant.DQM +
InfluxDbSqlConstant.RBK +
InfluxDbSqlConstant.AS_VALUE;
selectColumns.add(selectFragment);
return this;
}
/***
* 获取指定字段最大值的集合
* @author hongawen
* @param columnName 表字段名
* @return InfluxQueryWrapper
* 输出TOP("columnName",number)
*/
public InfluxQueryWrapper top(String columnName, int num) {
String selectFragment = InfluxDbSqlConstant.TOP +
InfluxDbSqlConstant.LBK +
InfluxDbSqlConstant.DQM +
columnName +
InfluxDbSqlConstant.DQM +
StrPool.COMMA +
num +
InfluxDbSqlConstant.RBK +
InfluxDbSqlConstant.AS_VALUE;
selectColumns.add(selectFragment);
return this;
}
/***
* 获取指定字段最小值的集合
* @author hongawen
* @param columnName 表字段名
* @return InfluxQueryWrapper
* 输出BOTTOM("columnName",number)
*/
public InfluxQueryWrapper bottom(String columnName, int num) {
String selectFragment = InfluxDbSqlConstant.BOTTOM +
InfluxDbSqlConstant.LBK +
InfluxDbSqlConstant.DQM +
columnName +
InfluxDbSqlConstant.DQM +
StrPool.COMMA +
num +
InfluxDbSqlConstant.RBK +
InfluxDbSqlConstant.AS_VALUE;
selectColumns.add(selectFragment);
return this;
}
/***
* 注:该函数还需调研,暂时不要用
* 统计指定字段邻近值的变化率
* @author hongawen
* @param columnName 表字段名
* @return InfluxQueryWrapper
* 输出DERIVATIVE("columnName")
*/
@Deprecated
public InfluxQueryWrapper derivative(String columnName) {
String selectFragment = InfluxDbSqlConstant.DERIVATIVE +
InfluxDbSqlConstant.LBK +
InfluxDbSqlConstant.DQM +
columnName +
InfluxDbSqlConstant.DQM +
InfluxDbSqlConstant.RBK +
InfluxDbSqlConstant.AS_VALUE;
selectColumns.add(selectFragment);
return this;
}
/***
* 统计指定字段值时间戳最近的值
* @author hongawen
* @param columnName 表字段名
* @return InfluxQueryWrapper
* 输出LAST("columnName")
*/
public InfluxQueryWrapper last(String columnName) {
String selectFragment = InfluxDbSqlConstant.LAST +
InfluxDbSqlConstant.LBK +
InfluxDbSqlConstant.DQM +
columnName +
InfluxDbSqlConstant.DQM +
InfluxDbSqlConstant.RBK +
InfluxDbSqlConstant.AS_VALUE;
selectColumns.add(selectFragment);
return this;
}
/***
* 获取指定字段最大值
* @author hongawen
* @param columnName 表字段名
* @return InfluxQueryWrapper
* 输出 MAX("columnName")
*/
public InfluxQueryWrapper max(String columnName) {
return max(columnName, "value");
}
/***
* 获取指定字段最大值
* @author hongawen
* @param columnName 表字段名
* @param resultName 映射名称
* @return InfluxQueryWrapper
* 输出 MAX("columnName") as resultName
*/
public InfluxQueryWrapper max(String columnName, String resultName) {
String selectFragment = InfluxDbSqlConstant.MAX +
InfluxDbSqlConstant.LBK +
InfluxDbSqlConstant.DQM +
columnName +
InfluxDbSqlConstant.DQM +
InfluxDbSqlConstant.RBK +
InfluxDbSqlConstant.AS +
resultName +
StrPool.C_SPACE;
selectColumns.add(selectFragment);
return this;
}
/***
* 获取指定字段最小值
* @author hongawen
* @param columnName 表字段名
* @return InfluxQueryWrapper
* 输出 MIN("columnName")
*/
public InfluxQueryWrapper min(String columnName) {
return min(columnName, "value");
}
/***
* 获取指定字段最小值
* @author hongawen
* @param columnName 表字段名
* @param resultName 映射名称
* @return InfluxQueryWrapper
* 输出 MIN("columnName") as resultName
*/
public InfluxQueryWrapper min(String columnName, String resultName) {
String selectFragment = InfluxDbSqlConstant.MIN +
InfluxDbSqlConstant.LBK +
InfluxDbSqlConstant.DQM +
columnName +
InfluxDbSqlConstant.DQM +
InfluxDbSqlConstant.RBK +
InfluxDbSqlConstant.AS +
resultName +
StrPool.C_SPACE;
selectColumns.add(selectFragment);
return this;
}
/***
* 返回field key较大的百分之N的值。
* @author hongawen
* @param columnName 表字段名
* @param percent 百分之percent
* @return InfluxQueryWrapper
* 输出 PERCENTILE("columnName",95)
*/
public InfluxQueryWrapper percentile(String columnName, int percent) {
return percentile(columnName, "value", percent);
}
/***
* 返回field key较大的百分之N的值。
* @author hongawen
* @param columnName 表字段名
* @param resultName 映射名称
* @param percent 百分之percent
* @return InfluxQueryWrapper
* 输出 PERCENTILE("columnName",95) as resultName
*/
public InfluxQueryWrapper percentile(String columnName, String resultName, int percent) {
String selectFragment = InfluxDbSqlConstant.PERCENTILE +
InfluxDbSqlConstant.LBK +
InfluxDbSqlConstant.DQM +
columnName +
InfluxDbSqlConstant.DQM +
StrPool.COMMA +
percent +
InfluxDbSqlConstant.RBK +
InfluxDbSqlConstant.AS +
resultName +
StrPool.C_SPACE;
selectColumns.add(selectFragment);
return this;
}
/**************************自定义查询条件比如between、>、<、=、>=、<=等等**************************/
/***
* 注influxdb
* 在WHERE子句中单引号来表示字符串字段值。具有无引号字符串字段值或双引号字符串字段值的查询将不会返回任何数据
* ,并且在大多数情况下也不会返回错误。
* @author hongawen
* @param fieldName 字段名
* @param val1 起始值
* @param val2 结束值
* @return InfluxQueryWrapper
* 输出为time >='2022-04-30 16:00:00' AND time <='2022-05-30 16:00:00'
*/
public InfluxQueryWrapper between(String fieldName, Object val1, Object val2) {
StringBuilder selectFragment = new StringBuilder();
Field field = this.getTargetClassField(measurement, fieldName);
String columnName = this.getColumnName(field, fieldName);
selectFragment.append(StrPool.C_SPACE)
.append(columnName)
.append(InfluxDbSqlConstant.GE);
if (val1 instanceof String) {
//需要用单引号包装下
selectFragment.append(InfluxDbSqlConstant.QM)
.append(val1)
.append(InfluxDbSqlConstant.QM)
.append(InfluxDbSqlConstant.AND)
.append(columnName)
.append(InfluxDbSqlConstant.LE)
.append(InfluxDbSqlConstant.QM)
.append(val2)
.append(InfluxDbSqlConstant.QM);
} else {
selectFragment.append(val1)
.append(InfluxDbSqlConstant.AND)
.append(columnName)
.append(InfluxDbSqlConstant.LE)
.append(val2);
}
this.conditions.add(selectFragment.toString());
return this;
}
/***
* 指定字段等于某个值
* @author hongawen
* @param columnName 表字段名
* @param columnValue 数值
* @return InfluxQueryWrapper
* 输出 columnName = columnValue
*/
public InfluxQueryWrapper eq(String columnName, Object columnValue) {
StringBuilder selectFragment = new StringBuilder();
selectFragment.append(columnName)
.append(InfluxDbSqlConstant.EQ);
if (columnValue instanceof String) {
//需要用单引号包装下
selectFragment.append(InfluxDbSqlConstant.QM)
.append(columnValue)
.append(InfluxDbSqlConstant.QM);
} else {
selectFragment.append(columnValue);
}
conditions.add(selectFragment.toString());
return this;
}
/***
* 指定字段大于某个值
* @author hongawen
* @param columnName 表字段名
* @param columnValue 数值
* @return InfluxQueryWrapper
* 输出 columnName > columnValue
*/
public InfluxQueryWrapper gt(String columnName, Object columnValue) {
StringBuilder selectFragment = new StringBuilder();
selectFragment.append(columnName)
.append(InfluxDbSqlConstant.GT);
if (columnValue instanceof String) {
//需要用单引号包装下
selectFragment.append(InfluxDbSqlConstant.QM)
.append(columnValue)
.append(InfluxDbSqlConstant.QM);
} else {
selectFragment.append(columnValue);
}
conditions.add(selectFragment.toString());
return this;
}
/***
* 指定字段大于等于某个值
* @author hongawen
* @param columnName 表字段名
* @param columnValue 数值
* @return InfluxQueryWrapper
* 输出 columnName >= columnValue
*/
public InfluxQueryWrapper ge(String columnName, Object columnValue) {
StringBuilder selectFragment = new StringBuilder();
selectFragment.append(columnName)
.append(InfluxDbSqlConstant.GE);
if (columnValue instanceof String) {
//需要用单引号包装下
selectFragment.append(InfluxDbSqlConstant.QM)
.append(columnValue)
.append(InfluxDbSqlConstant.QM);
} else {
selectFragment.append(columnValue);
}
conditions.add(selectFragment.toString());
return this;
}
/***
* 指定字段小于某个值
* @author hongawen
* @param columnName 表字段名
* @param columnValue 数值
* @return InfluxQueryWrapper
* 输出 columnName < columnValue
*/
public InfluxQueryWrapper lt(String columnName, Object columnValue) {
StringBuilder selectFragment = new StringBuilder();
selectFragment.append(columnName)
.append(InfluxDbSqlConstant.LT);
if (columnValue instanceof String) {
//需要用单引号包装下
selectFragment.append(InfluxDbSqlConstant.QM)
.append(columnValue)
.append(InfluxDbSqlConstant.QM);
} else {
selectFragment.append(columnValue);
}
conditions.add(selectFragment.toString());
return this;
}
/***
* 指定字段小于等于某个值
* @author hongawen
* @param columnName 表字段名
* @param columnValue 数值
* @return InfluxQueryWrapper
* 输出 columnName <= columnValue
*/
public InfluxQueryWrapper le(String columnName, Object columnValue) {
StringBuilder selectFragment = new StringBuilder();
selectFragment.append(columnName)
.append(InfluxDbSqlConstant.LE);
if (columnValue instanceof String) {
//需要用单引号包装下
selectFragment.append(InfluxDbSqlConstant.QM)
.append(columnValue)
.append(InfluxDbSqlConstant.QM);
} else {
selectFragment.append(columnValue);
}
conditions.add(selectFragment.toString());
return this;
}
/********************* [WHERE_clause] [GROUP_BY_clause] [ORDER_BY_clause] [LIMIT_clause] [OFFSET_clause] [SLIMIT_clause] [SOFFSET_clause]*********************/
/***
* 指定字段分组
* @author hongawen
* @param columnName 表字段名
* @return InfluxQueryWrapper
* 输出 columnName
*/
public InfluxQueryWrapper groupBy(String columnName) {
groupColumn.add(columnName);
return this;
}
/***
* 指定字段降序
* @author hongawen
* @return InfluxQueryWrapper
* 输出 time desc
*/
public InfluxQueryWrapper timeDesc() {
String selectFragment = InfluxDbSqlConstant.TIME
+ InfluxDbSqlConstant.DESC;
orderColumn.add(selectFragment);
return this;
}
/***
* 指定字段升序
* @author hongawen
* @return InfluxQueryWrapper
* 输出 time asc
*/
public InfluxQueryWrapper timeAsc( ) {
String selectFragment = InfluxDbSqlConstant.TIME
+ InfluxDbSqlConstant.ASC;
orderColumn.add(selectFragment);
return this;
}
/***
* 根据配置后的实体生成对应的sql
* @author hongawen
* @return String 最终查询的sql语句
*/
public String generateSql() {
this.sqlSelect.setLength(0);
this.sqlSelect.append(InfluxDbSqlConstant.SELECT);
//判断用户需要返回的属性
if (CollectionUtil.isEmpty(selectColumns)) {
sqlSelect.append(InfluxDbSqlConstant.ALL)
.append(InfluxDbSqlConstant.FROM)
.append(InfluxDbSqlConstant.DQM)
.append(measurement.getSimpleName().toLowerCase())
.append(InfluxDbSqlConstant.DQM);
} else {
//将集合处理成查询属性
sqlSelect.append(String.join(StrPool.COMMA, selectColumns))
.append(InfluxDbSqlConstant.FROM)
.append(InfluxDbSqlConstant.DQM)
.append(measurement.getSimpleName().toLowerCase())
.append(InfluxDbSqlConstant.DQM);
}
//判断是否有查询条件
if (CollectionUtil.isNotEmpty(conditions)) {
sqlSelect.append(InfluxDbSqlConstant.WHERE)
.append(String.join(InfluxDbSqlConstant.AND, conditions));
}
//判断是否有分组
if (CollectionUtil.isNotEmpty(groupColumn)) {
sqlSelect.append(InfluxDbSqlConstant.GB)
.append(String.join(StrPool.COMMA, groupColumn));
}
//判断是否有排序
if (CollectionUtil.isNotEmpty(orderColumn)) {
sqlSelect.append(InfluxDbSqlConstant.OB)
.append(String.join(StrPool.COMMA, orderColumn));
}
//最后拼接上时区
sqlSelect.append(InfluxDbSqlConstant.TZ);
return sqlSelect.toString();
}
/***
*
* @author hongawen
* @param beanClass 实体类
* @param fieldName 属性名
* @return Field 属性
*/
private Field getTargetClassField(Class<?> beanClass, String fieldName) {
Field field = ReflectUtil.getField(beanClass, fieldName);
if (Objects.isNull(field)) {
throw new RuntimeException(fieldName + "在目标实体类中不存在!!!");
}
return field;
}
/***
* 获取sql拼接的名称存在注解名就用注解名否则就用属性名
* @author hongawen
* @param field 属性
* @param fieldName 属性名
* @return String
*/
private String getColumnName(Field field, String fieldName) {
Column column = field.getAnnotation(Column.class);
//数据库字段
String influxColumn;
if (Objects.isNull(column)) {
//没有注解,就用属性名
influxColumn = fieldName;
} else {
//获取注解映射的名称
influxColumn = column.name();
}
return influxColumn;
}
}