https://github.com/influxdata/influxdb-client-java/issues/346
行转列的翻转
influxdb中数据定义:
- 如果对象是内部类,必须定义为static,外部类不用。
- 类上不一定用注解@Measurement(name = "common") 指定表的名称,可以在程序中拼接。
- 数据列上,也不用 @Column 设定属性, 时间列也不用,就可以。
- 属性名字,camerl或者下划线都可以,会自动映射,
- 如果接受类中不能包括所有influxdb表中的field,多余被丢弃,名字对不上的也丢弃。
- 读取回来数据是强类型,
influxdb 的field 只有4中类型:Field values can be floats, integers, strings, or Booleans:
结构下:
// @Measurement(name = "common")
public class Common
{
// @Column
Double airPressAll;
// @Column
Double air_temp_all;
//上面两种命名方式都可以,框架中有格式转化
// @Column(timestamp = true)
Instant time;
}
读取代码:重点使用 pivot函数,把行转列,原理如下图:
Restrictions restrictions = Restrictions.and(Restrictions.measurement().equal("common"));
char[] tokenChar = token.toCharArray();
InfluxDBClient influxDBClient = InfluxDBClientFactory.create(host, tokenChar, org, bucket);
QueryApi queryApi = influxDBClient.getQueryApi();
long start = -300;
long end = 0;
Flux flux = Flux.from("cqe").range(start, end, ChronoUnit.SECONDS).filter(restrictions).pivot()
.withRowKey(new String[]{"_time"})
.withColumnKey(new String[]{"_field"})
.withValueColumn("_value");
List<Common> query = queryApi.query(flux.toString(), Common.class);
influxDBClient.close();
会自动,把行数据,转为列数据类似mysql结果。
附上转换的源码:influxdb-client-core-5.0.5jar
/**
* Maps FluxRecord into custom POJO class.
*
* @param record flux record
* @param clazz target class
* @param <T> pojo type
* @return
*/
@Nonnull
public <T> T toPOJO(@Nonnull final FluxRecord record, @Nonnull final Class<T> clazz) {
Objects.requireNonNull(record, "Record is required");
Objects.requireNonNull(clazz, "Class type is required");
try {
T pojo = clazz.newInstance();
Class<?> currentClazz = clazz;
while (currentClazz != null) {
Field[] fields = currentClazz.getDeclaredFields();
for (Field field : fields) {
Column anno = field.getAnnotation(Column.class);
String columnName = field.getName();
if (anno != null && !anno.name().isEmpty()) {
columnName = anno.name();
}
Map<String, Object> recordValues = record.getValues();
String col = null;
if (recordValues.containsKey(columnName)) {
col = columnName;
} else if (recordValues.containsKey("_" + columnName)) {
col = "_" + columnName;
} else if (anno != null && anno.measurement()) {
col = "_measurement";
} else {
String columnNameInSnakeCase = camelCaseToSnakeCase(columnName);
if (recordValues.containsKey(columnNameInSnakeCase)) {
col = columnNameInSnakeCase;
}
}
if (col != null) {
Object value = record.getValueByKey(col);
setFieldValue(pojo, field, value);
}
}
currentClazz = currentClazz.getSuperclass();
}
return pojo;
} catch (Exception e) {
throw new InfluxException(e);
}
}
private String camelCaseToSnakeCase(final String str) {
return CAMEL_CASE_TO_SNAKE_CASE_REPLACE_PATTERN.matcher(str)
.replaceAll("_$0")
.toLowerCase();
}