1. 相关的官方文档
(join语法)中文官方文档:https://docs.influxdb.org.cn/influxdb/v2/query-data/flux/join/
英文官方文档:Join data in InfluxDB with Flux | InfluxDB OSS v2 Documentation
JAVA集成官方文档:https://github.com/influxdata/influxdb-client-java
InfluxDB2.x官方安装中文文档:https://docs.influxdb.org.cn/influxdb/v2/install/
2. WEB UI
2.X版本是有web ui的,地址:http://IP地址:8086,详情查看上述的官方安装文档。
3. maven
我的环境是JAVA11,所以使用的是6.12.0版本,7.x版本要求JAVA17.
<!-- 7.x 要求java17 -->
<dependency>
<groupId>com.influxdb</groupId>
<artifactId>influxdb-client-java</artifactId>
<version>6.12.0</version>
</dependency>
<dependency>
<groupId>com.influxdb</groupId>
<artifactId>influxdb-client-flux</artifactId>
<version>6.12.0</version>
</dependency>
4. yml配置
influx:
url: http://ip地址:端口
org: 你的组织名称
token: 桶操作Token
bucket: 桶名称
connectTimeout: 10000
readTimeout: 120000
writeTimeout: 120000
5. InfluxDBClient
package org.example.series.influxdb.conf;
import com.influxdb.client.InfluxDBClient;
import com.influxdb.client.InfluxDBClientFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Copyright © All rights Reserved, Designed By
*
* @Description:
* @date: 2025-06-12 10:33
*/
@Slf4j
@Configuration
@EnableConfigurationProperties(InfluxProperties.class)
public class InfluxDB2Conf implements DisposableBean {
@Value("${vms.repository.influx.url}")
public String url;
@Value("${vms.repository.influx.token}")
public char[] token;
@Value("${vms.repository.influx.orgName}")
public String orgName;
private volatile InfluxDBClient influxDBClient;
@Bean
public InfluxDBClient InfluxDBClient() {
influxDBClient = InfluxDBClientFactory
.create(url, token, orgName);
return influxDBClient;
}
@Override
public void destroy() throws Exception {
if (influxDBClient != null) {
influxDBClient.close();
log.info("InfluxDB 客户端已安全关闭");
}
}
}
6. 实体类
package org.example.series.influxdb.model;
import com.influxdb.annotations.Column;
import com.influxdb.annotations.Measurement;
import lombok.Data;
import java.io.Serializable;
import java.time.Instant;
/**
* Copyright © All rights Reserved, Designed By
*
* @Description:
* @date: 2025-06-12 14:35
*/
@Data
@Measurement(name = "people_test5")
public class People implements Serializable {
private static final long serialVersionUID = 1L;
@Column(tag = true)
private String name;
@Column(name = "age")
private Double age;
@Column(name = "phone")
private String phone;
@Column(name = "mail")
private String mail;
@Column(name = "dataTime")
private Long dataTime;
/**
* TODO @Column指定timestamp = true是必须是Instant类型,对于经纬度数据,可能存在时间戳相同的情况,influxdb2.x中时间戳相同会出现数据覆盖情况
* todo GPS时间格式:YY-MM-DD-hh-mm-ss(GMT+8 设备上报采用北京时间基准)
*/
@Column(timestamp = true)
private Instant time;
}
7. 测试类
package org.example.series.influxdb;
import cn.hutool.json.JSONUtil;
import com.influxdb.client.InfluxDBClient;
import com.influxdb.client.QueryApi;
import lombok.extern.slf4j.Slf4j;
import org.example.series.influxdb.model.People;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
/**
* Copyright © All rights Reserved, Designed By
*
* @Description:
* @date: 2025-06-12 11:14
*/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class InfluxDB2FluxUtilTest {
@Resource
private InfluxDBClient influxDBClient;
/**
* 功能描述: 右连接查询测试 <br>
* 〈〉
* 比如:A right join B:
* ①首先要知道A和B的数据来源
* ②flux join脚本:
* import "array"
* import "join"
* // A
* a_table_source = from(bucket:"test_db")
* |> range(start: 0)
* |> filter(fn: (r) => r._measurement == "people_test5")
* |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")
* |> group(columns: [])
*
* // B (参考:https://docs.influxdata.com/flux/v0/stdlib/array/from/)
* nameArray = [
* "0d8rm",
* "1jtym"
* ]
*
* nameObjArray = nameArray |> array.map(fn: (x) => ({name: x}))
* b_table_source = array.from(rows: nameObjArray)
*
* // 右连接查询(参考:https://docs.influxdata.com/flux/v0/stdlib/join/right/)
* join.right(
* left: a_table_source,
* right: b_table_source,
* on: (l, r) => l.name == r.name,
* as: (l, r) => ({name: l.name, age: l.age, mail: l.mail,dataTime: l.dataTime, v_right_name: r.name}),
* )
*
* 输出结果:
* [{"name":"0d8rm","age":61.94892750825298,"mail":"7351l54i","dataTime":1750232700019},{"name":"1jtym","age":51.029512726383295,"mail":"japtclsh","dataTime":1749901499654}]
*
*
* @Param: []
* @Return: void
* @Author: LHP LHP@gmail.com
* @Date: 2025-06-16 11:16
*/
@Test
public void right_joinTest() {
String flux =
"import \"array\"\n" +
"import \"join\"\n"+
"\n" +
"a_table_source = from(bucket:\"test_db\") \n" +
"|> range(start: 0) \n" +
"|> filter(fn: (r) => r._measurement == \"people_test5\") \n" +
"|> pivot(rowKey:[\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\") \n" +
"|> group(columns: []) \n" +
"\n" +
"a = [\n" +
" \"0d8rm\",\n" +
" \"1jtym\"\n" +
"]\n" +
"b = a |> array.map(fn: (x) => ({name: x}))\n" +
"b_table_source = array.from(rows: b)\n" +
"\n" +
"join.right(\n" +
" left: a_table_source,\n" +
" right: b_table_source,\n" +
" on: (l, r) => l.name == r.name,\n" +
" as: (l, r) => ({name: l.name, age: l.age, mail: l.mail,dataTime: l.dataTime, v_right_name: r.name}),\n" +
")";
QueryApi queryApi = influxDBClient.getQueryApi();
log.info("right_joinTest=====flux:{}", flux);
List<People> list = queryApi.query(flux, People.class);
System.out.println(JSONUtil.toJsonStr(list));
}
}