【功能优化】IoT:清理通用 TDengine 封装,使用 SQL 查询

This commit is contained in:
YunaiV 2025-01-27 14:23:34 +08:00
parent 8089f3a319
commit b319485ca6
15 changed files with 5 additions and 951 deletions

View File

@ -1,85 +0,0 @@
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelProperty;
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelRespVO;
import java.util.HashMap;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
/**
* FieldParser 类用于解析和转换物模型字段到 TDengine 字段
*/
public class FieldParser {
/**
* 物模型到td数据类型映射
*/
@Deprecated
private static final HashMap<String, String> TYPE_MAPPING = new HashMap<>() {
{
put("INT", "INT");
put("FLOAT", "FLOAT");
put("DOUBLE", "DOUBLE");
put("BOOL", "BOOL");
put("ENUM", "NCHAR");
put("TEXT", "NCHAR");
put("DATE", "NCHAR");
}
};
/**
* 将物模型字段转换为td字段
*
* @param property 物模型属性
* @return TdField对象
*/
public static TdFieldDO parse(ThingModelProperty property) {
// 将物模型字段类型映射为 td 字段类型
String fieldName = property.getIdentifier().toLowerCase();
String fType = TYPE_MAPPING.get(property.getDataType().toUpperCase());
// 如果字段类型为NCHAR默认长度为64
int dataLength = 0;
if ("NCHAR".equals(fType)) {
dataLength = 64;
}
return new TdFieldDO(fieldName, fType, dataLength);
}
/**
* 从物模型中获取字段列表
*
* @param thingModel 物模型响应对象
* @return 字段列表
*/
public static List<TdFieldDO> parse(ThingModelRespVO thingModel) {
return convertList(thingModel.getModel().getProperties(), FieldParser::parse);
}
/**
* 将从库中查出来的字段信息转换为 TDengine 字段对象
*
* @param rows 从库中查出的字段信息列表
* @return 转换后的 TDengine 字段对象列表
*/
public static List<TdFieldDO> parse(List<List<Object>> rows) {
return convertList(rows, row -> {
String type = row.get(1).toString().toUpperCase();
// TODO @puhui999"NCHAR" 最好枚举下
int dataLength = "NCHAR".equals(type) ? Integer.parseInt(row.get(2).toString()) : -1;
return new TdFieldDO(row.get(0).toString(), type, dataLength);
});
}
/**
* 获取字段字义
*/
@Deprecated
public static String getFieldDefine(TdFieldDO field) {
return "`" + field.getFieldName() + "`" + " "
+ (field.getDataLength() > 0 ? String.format("%s(%d)", field.getDataType(), field.getDataLength())
: field.getDataType());
}
}

View File

@ -1,48 +0,0 @@
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
import lombok.Data;
// TODO @haohao类似这个其实可以参考 mybatis plusquerywrapper搞个 TdEngineQueryWrapper这样看起来会更好懂
/**
* 查询DO
*/
@Data
@Deprecated
public class SelectDO {
// TODO @haohadatabase 是个单词
/**
* 数据库名称
*/
private String dataBaseName;
/**
* 超级表名称
*/
private String tableName;
/**
* 查询字段
*/
private String fieldName;
/**
* 开始时间
*/
private Long startTime;
/**
* 结束时间
*/
private Long endTime;
/**
* 查询类型
*/
private String type;
/**
* 设备ID
*/
private String deviceId;
}

View File

@ -1,37 +0,0 @@
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
import lombok.Data;
/**
* tags查询DO
*/
@Data
@Deprecated
public class TagsSelectDO {
/**
* 数据库名称
*/
private String dataBaseName;
/**
* 超级表名称
*/
private String stableName;
/**
* tags名称
*/
private String tagsName;
/**
* tags值
*/
private Long startTime;
/**
* tags值
*/
private Long endTime;
}

View File

@ -1,49 +0,0 @@
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
// TODO 芋艿看看是不是后续简化掉
/**
* TD 引擎的字段
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Deprecated
public class TdFieldDO {
/**
* 字段名称
*/
private String fieldName;
/**
* 字段类型
*/
private String dataType;
/**
* 字段长度
*/
private Integer dataLength = 0;
/**
* 字段值
*/
private Object fieldValue;
public TdFieldDO(String fieldName, String dataType, Integer dataLength) {
this.fieldName = fieldName;
this.dataType = dataType;
this.dataLength = dataLength;
}
public TdFieldDO(String fieldName, Object fieldValue) {
this.fieldName = fieldName;
this.fieldValue = fieldValue;
}
}

View File

@ -1,42 +0,0 @@
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* TdResponse 类用于处理 TDengine 的响应
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Deprecated
public class TdResponse {
public static final int CODE_SUCCESS = 0;
public static final int CODE_TB_NOT_EXIST = 866;
/**
* 状态
*/
private String status;
/**
* 错误码
*/
private int code;
/**
* 错误信息
*/
private String desc;
/**
* 列信息
* [["time","TIMESTAMP",8,""],["powerstate","TINYINT",1,""],["brightness","INT",4,""],["deviceid","NCHAR",32,"TAG"]]
*/
private List data;
}

View File

@ -1,59 +0,0 @@
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
// TODO @haohao有部分非实体的部分是不是可以搞到 iot framework 包下搞个 tdengine 作为框架级的封装放在 dataobject感觉不是很合理哈可以微信讨论下
/**
* TdRestApi 类用于处理 TDengine REST API 请求
*/
@Slf4j
@Service
@Deprecated // TODO 芋艿貌似没用到
public class TdRestApi {
@Value("${spring.datasource.dynamic.datasource.tdengine.url}")
private String url;
@Value("${spring.datasource.dynamic.datasource.tdengine.username}")
private String username;
@Value("${spring.datasource.dynamic.datasource.tdengine.password}")
private String password;
/**
* 获取 REST API URL
*/
private String getRestApiUrl() {
String restUrl = url.replace("jdbc:TAOS-RS://", "")
.replaceAll("\\?.*", "");
int idx = restUrl.lastIndexOf("/");
return String.format("%s/rest/sql/%s", restUrl.substring(0, idx), restUrl.substring(idx + 1));
}
/**
* 新建td api请求对象
*/
public HttpRequest newApiRequest(String sql) {
return HttpRequest
.post(getRestApiUrl())
.body(sql)
.basicAuth(username, password);
}
/**
* 执行sql
*/
public TdResponse execSql(String sql) {
log.info("exec td sql:{}", sql);
HttpRequest request = newApiRequest(sql);
HttpResponse response = request.execute();
return JSONUtil.toBean(response.body(), TdResponse.class);
}
}

View File

@ -1,71 +0,0 @@
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Deprecated
/**
* TD 引擎的数据库
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TdTableDO {
/**
* 数据库名称
*/
private String dataBaseName;
// TODO @haohaosuperTableName tableName 是不是合并因为每个 mapper 操作的时候有且只会使用到其中一个
/**
* 超级表名称
*/
private String superTableName;
/**
* 表名称
*/
private String tableName;
private String productKey;
private String deviceKey;
/**
* COLUMN 字段
*/
private TdFieldDO column;
/**
* TAG 字段
*/
private TdFieldDO tag;
/**
* COLUMN 字段 - 列表
*/
private List<TdFieldDO> columns;
/**
* TAG 字段 - 列表
*/
private List<TdFieldDO> tags;
public TdTableDO(String dataBaseName, String superTableName, List<TdFieldDO> columns, List<TdFieldDO> tags) {
this.dataBaseName = dataBaseName;
this.superTableName = superTableName;
this.columns = columns;
this.tags = tags;
}
public TdTableDO(String dataBaseName, String superTableName) {
this.dataBaseName = dataBaseName;
this.superTableName = superTableName;
}
}

View File

@ -1,61 +0,0 @@
package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
// TODO @芋艿纠结下字段
@Deprecated // TODO @super看看啥时候删除下哈
/**
* TD 物模型消息日志的数据库
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ThingModelMessageDO {
/**
* 消息 ID
*/
private String id;
/**
* 系统扩展参数
*
* 例如设备状态系统时间固件版本等系统级信息
*/
private Object system;
/**
* 请求方法
*
* 例如thing.event.property.post
*/
private String method;
/**
* 请求参数
*/
private Object params;
/**
* 属性上报时间戳
*/
private Long time;
/**
* 设备信息
*/
private String productKey;
/**
* 设备 key
*/
private String deviceKey;
}

View File

@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField;
import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
@ -78,27 +77,6 @@ public interface IotDevicePropertyDataMapper {
void alterProductPropertySTableDropField(@Param("productKey") String productKey,
@Param("field") TDengineTableField field);
//TODO:先参考一下老逻辑后续改进
/**
* 插入数据 - 指定列插入数据
*
* @param table 数据
* productKey 产品 key
* deviceKey 设备 key
* columns
*/
void insertDevicePropertyData(TdTableDO table);
//TODO:先参考一下老逻辑后续改进
/**
* 查看超级表 - 获取超级表的结构信息
* SQLDESCRIBE [db_name.]stb_name;
*
* @param superTable 超级表信息
* productKey 产品 key
*/
List<Map<String, Object>> describeSuperTable(TdTableDO superTable);
/**
* 获取历史数据列表
*

View File

@ -1,147 +0,0 @@
package cn.iocoder.yudao.module.iot.dal.tdengine;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
import com.baomidou.dynamic.datasource.annotation.DS;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* 专门处理 DDL数据定义语言操作包含所有的数据库和表的定义操作例如创建数据库创建超级表创建子表等
*/
@Mapper
@DS("tdengine")
public interface TdEngineDDLMapper {
/**
* 创建数据库
* SQLCREATE DATABASE [IF NOT EXISTS] db_name [database_options];
*
* @param dataBaseName 数据库名称
*/
@TenantIgnore
void createDatabase(@Param("dataBaseName") String dataBaseName);
/**
* 创建超级表
* SQLCREATE STABLE [IF NOT EXISTS] stb_name (create_definition [, create_definition] ...) TAGS (create_definition [, create_definition] ...) [table_options];
*
* @param superTable 超级表信息
* dataBaseName 数据库名称
* superTableName 超级表名称
* columns 列信息
* tags 标签信息
*/
@TenantIgnore
void createSuperTable(TdTableDO superTable);
/**
* 查看超级表 - 显示当前数据库下的所有超级表信息
* SQLSHOW STABLES [LIKE tb_name_wildcard];
*
* @param superTable 超级表信息
* dataBaseName 数据库名称
* superTableName 超级表名称
*/
@TenantIgnore
List<Map<String, Object>> showSuperTables(TdTableDO superTable);
/**
* 查看超级表 - 获取超级表的结构信息
* SQLDESCRIBE [db_name.]stb_name;
*
* @param superTable 超级表信息
* dataBaseName 数据库名称
* superTableName 超级表名称
*/
@TenantIgnore
List<Map<String, Object>> describeSuperTable(TdTableDO superTable);
/**
* 修改超级表 - 增加列
* SQLALTER STABLE stb_name ADD COLUMN col_name column_type;
*
* @param superTable 超级表信息
* dataBaseName 数据库名称
* superTableName 超级表名称
* column 列信息
*/
@TenantIgnore
void addColumnForSuperTable(TdTableDO superTable);
/**
* 修改超级表 - 删除列
* SQLALTER STABLE stb_name DROP COLUMN col_name;
*
* @param superTable 超级表信息
* dataBaseName 数据库名称
* superTableName 超级表名称
* column 列信息
*/
@TenantIgnore
void dropColumnForSuperTable(TdTableDO superTable);
/**
* 修改超级表 - 修改列宽
* SQLALTER STABLE stb_name MODIFY COLUMN col_name data_type(length);
*
* @param superTable 超级表信息
* dataBaseName 数据库名称
* superTableName 超级表名称
* column 列信息
*/
@TenantIgnore
void modifyColumnWidthForSuperTable(TdTableDO superTable);
/**
* 修改超级表 - 为超级表添加标签
*
* @param superTable 超级表信息
* dataBaseName 数据库名称
* superTableName 超级表名称
* tag 标签信息
*/
@TenantIgnore
void addTagForSuperTable(TdTableDO superTable);
/**
* 修改超级表 - 为超级表删除标签
*
* @param superTable 超级表信息
* dataBaseName 数据库名称
* superTableName 超级表名称
* tag 标签信息
*/
@TenantIgnore
void dropTagForSuperTable(TdTableDO superTable);
/**
* 创建子表 - 创建子表
* SQLCREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...);
*
* @param table 表信息
* dataBaseName 数据库名称
* superTableName 超级表名称
* tableName 子表名称
* tags TAG 字段
*/
@TenantIgnore
void createTable(TdTableDO table);
/**
* 创建子表 - 创建子表并指定标签的值
* SQLCREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...);
*
* @param table 表信息
* dataBaseName 数据库名称
* superTableName 超级表名称
* tableName 子表名称
* tags TAG 字段
*/
@TenantIgnore
void createTableWithTags(TdTableDO table);
}

View File

@ -1,103 +0,0 @@
package cn.iocoder.yudao.module.iot.dal.tdengine;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
import com.baomidou.dynamic.datasource.annotation.DS;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
/**
* 专门处理 TD Engine DML数据操作语言操作处理所有的数据查询和写入操作如插入数据查询数据等
*/
@Mapper
@DS("tdengine")
public interface TdEngineDMLMapper {
/**
* 插入数据 - 指定列插入数据
*
* @param table 数据
* dataBaseName 数据库名
* tableName 表名
* columns
*/
@TenantIgnore
void insertData(TdTableDO table);
/**
* 根据时间戳查询数据
*
* @param selectDO 查询条件
* @return 查询结果列表
*/
@TenantIgnore
List<Map<String, Object>> selectByTimestamp(SelectDO selectDO);
/**
* 根据时间戳获取数据条数
*
* @param selectDO 查询条件
* @return 数据条数
*/
@TenantIgnore
Map<String, Long> selectCountByTimestamp(SelectDO selectDO);
/**
* 获取最新数据
*
* @param selectDO 查询条件
* @return 最新数据
*/
@TenantIgnore
Map<String, Object> selectOneLastData(SelectDO selectDO);
/**
* 获取历史数据列表
*
* @param selectVisualDO 查询条件
* @return 历史数据列表
*/
@TenantIgnore
List<Map<String, Object>> selectHistoryDataList(SelectVisualDO selectVisualDO);
/**
* 获取实时数据列表
*
* @param selectVisualDO 查询条件
* @return 实时数据列表
*/
@TenantIgnore
List<Map<String, Object>> selectRealtimeDataList(SelectVisualDO selectVisualDO);
/**
* 获取聚合数据列表
*
* @param selectVisualDO 查询条件
* @return 聚合数据列表
*/
@TenantIgnore
List<Map<String, Object>> selectAggregateDataList(SelectVisualDO selectVisualDO);
/**
* 根据标签获取最新数据列表
*
* @param tagsSelectDO 查询条件
* @return 最新数据列表
*/
@TenantIgnore
List<Map<String, Object>> selectLastDataListByTags(TagsSelectDO tagsSelectDO);
/**
* 获取历史数据条数
*
* @param selectVisualDO 查询条件
* @return 数据条数
*/
@TenantIgnore
Long selectHistoryCount(SelectVisualDO selectVisualDO);
}

View File

@ -5,17 +5,17 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
/**
* TDengine 表初始化的 Configuration
*
* @author alwayssuper
*/
@Configuration
@Slf4j
@Component
@RequiredArgsConstructor
public class TDengineTableInitConfiguration implements ApplicationRunner {
@Slf4j
public class TDengineTableInitRunner implements ApplicationRunner {
private final IotDeviceLogService deviceLogService;
@ -26,7 +26,7 @@ public class TDengineTableInitConfiguration implements ApplicationRunner {
deviceLogService.defineDeviceLog();
} catch (Exception ex) {
// 初始化失败时打印错误日志并退出系统
log.error("[TDengine] 初始化设备日志表结构失败,系统无法正常运行,即将退出", ex);
log.error("[run][TDengine初始化设备日志表结构失败系统无法正常运行即将退出]", ex);
System.exit(1);
}
}

View File

@ -1,101 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper">
<!-- 创建数据库 -->
<update id="createDatabase" parameterType="String">
CREATE DATABASE IF NOT EXISTS ${dataBaseName}
</update>
<!-- 创建超级表 -->
<update id="createSuperTable">
CREATE STABLE IF NOT EXISTS ${dataBaseName}.${superTableName}
<foreach item="item" collection="columns" separator=","
open="(" close=")">
${item.fieldName} ${item.dataType}
<if test="item.dataLength > 0">
(${item.dataLength})
</if>
</foreach>
TAGS
<foreach item="item" collection="tags" separator=","
open="(" close=")">
${item.fieldName} ${item.dataType}
<if test="item.dataLength > 0">
(${item.dataLength})
</if>
</foreach>
</update>
<!-- 查看超级表 -->
<select id="showSuperTables" resultType="java.util.Map">
SHOW ${dataBaseName}.STABLES LIKE '${superTableName}'
</select>
<!-- 描述超级表结构 -->
<select id="describeSuperTable" resultType="java.util.Map">
DESCRIBE ${dataBaseName}.${superTableName}
</select>
<!-- 为超级表添加列 -->
<update id="addColumnForSuperTable">
ALTER STABLE ${dataBaseName}.${superTableName} ADD COLUMN ${column.fieldName} ${column.dataType}
<if test="column.dataLength > 0">
(${column.dataLength})
</if>
</update>
<!-- 为超级表删除列 -->
<update id="dropColumnForSuperTable">
ALTER STABLE ${dataBaseName}.${superTableName} DROP COLUMN ${column.fieldName}
</update>
<!-- 修改列宽 -->
<update id="modifyColumnWidthForSuperTable">
ALTER STABLE ${dataBaseName}.${superTableName} MODIFY COLUMN ${column.fieldName} ${column.dataType}
<if test="column.dataLength > 0">
(${column.dataLength})
</if>
</update>
<!-- 为超级表添加标签 -->
<update id="addTagForSuperTable">
ALTER STABLE ${dataBaseName}.${superTableName} ADD TAG ${tag.fieldName} ${tag.dataType}
<if test="tag.dataLength > 0">
(${tag.dataLength})
</if>
</update>
<!-- 为超级表删除标签 -->
<update id="dropTagForSuperTable">
ALTER STABLE ${dataBaseName}.${superTableName} DROP TAG ${tag.fieldName}
</update>
<!-- 创建子表 -->
<update id="createTable">
CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName}
USING ${dataBaseName}.${superTableName}
TAGS
<foreach item="item" collection="tags" separator=","
open="(" close=")">
#{item.fieldValue}
</foreach>
</update>
<!-- 创建子表,带有 TAGS -->
<update id="createTableWithTags">
CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName}
USING ${dataBaseName}.${superTableName}
<foreach item="item" collection="tags" separator="," open="(" close=")">
#{item.fieldName}
</foreach>
TAGS
<foreach item="item" collection="tags" separator=","
open="(" close=")">
#{item.fieldValue}
</foreach>
</update>
</mapper>

View File

@ -1,86 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper">
<!-- 插入数据 -->
<insert id="insertData">
INSERT INTO ${dataBaseName}.${tableName}
<foreach item="item" collection="columns" separator=","
open="(" close=")">
${item.fieldName}
</foreach>
VALUES
<foreach item="item" collection="columns" separator=","
open="(" close=")">
#{item.fieldValue}
</foreach>
</insert>
<!-- 根据时间戳查询数据 -->
<select id="selectByTimestamp" parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO"
resultType="Map">
SELECT * FROM ${dataBaseName}.${tableName}
WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime}
</select>
<!-- 获取时间范围内的数据条数 -->
<select id="selectCountByTimestamp" parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO"
resultType="java.util.Map">
SELECT COUNT(0) AS count
FROM ${dataBaseName}.${tableName}
WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime}
</select>
<!-- 获取最新数据 -->
<select id="selectOneLastData" resultType="java.util.Map">
SELECT LAST(time), *
FROM ${tableName}
WHERE device_id = #{deviceId}
</select>
<!-- 根据标签获取最新数据 -->
<select id="selectLastDataListByTags" parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO"
resultType="java.util.Map">
SELECT LAST(*)
FROM ${dataBaseName}.${stableName}
GROUP BY ${tagsName}
</select>
<!-- 获取历史数据 -->
<select id="selectHistoryDataList" resultType="java.util.Map"
parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO">
SELECT ${fieldName} AS data, time
FROM ${dataBaseName}.${tableName}
WHERE time BETWEEN #{startTime} AND #{endTime}
AND ${fieldName} IS NOT NULL
ORDER BY time DESC
LIMIT #{params.rows} OFFSET #{params.page}
</select>
<!-- 获取实时数据 -->
<select id="selectRealtimeDataList" resultType="java.util.Map"
parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO">
SELECT ${fieldName}, time
FROM ${dataBaseName}.${tableName}
</select>
<!-- 获取聚合数据 -->
<select id="selectAggregateDataList" resultType="java.util.Map"
parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO">
SELECT ${aggregate}(${fieldName})
FROM ${dataBaseName}.${tableName}
WHERE ts BETWEEN #{startTime} AND #{endTime} INTERVAL (${interval})
LIMIT #{num}
</select>
<!-- 获取历史数据条数 -->
<select id="selectHistoryCount" resultType="java.lang.Long">
SELECT COUNT(time)
FROM ${dataBaseName}.${tableName}
WHERE time BETWEEN #{startTime} AND #{endTime}
AND ${fieldName} IS NOT NULL
</select>
</mapper>

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdThingModelMessageMapper">
<!-- 创建物模型消息日志超级表 -->
<update id="createSuperTable">
CREATE STABLE thing_model_message_${productKey}(
ts TIMESTAMP,
id NCHAR(64),
sys NCHAR(2048),
method NCHAR(255),
params NCHAR(2048),
device_name NCHAR(64)
)TAGS (
device_key NCHAR(50)
)
</update>
<!-- 创建物模型消息日志子表带有deviceKey的TAG -->
<update id="createTableWithTag">
CREATE STABLE ${deviceKey}
USING thing_model_message_${productKey}(
ts,
id ,
sys ,
method ,
params ,
device_name
)TAGS(
#{device_key}
)
</update>
</mapper>