一、前话
最近在开发金融类的k线、盘口业务,而这些业务的海量数据如何存储,公司的技术选型,选择了MongoDB。
而对k线这类业务来说,查询历史数据是必要的功能,所以我便开始编写对MongoDB进行查询的接口,也就是在这个时候,问题出现了。
前端在调用接口时会发过来两个时间戳(必填),一个是开始时间(startTime),另一个是结束时间(endTime),我需要显示指定时间里的数据,我心想:OK,太容易了,我直接闭眼敲…
二、代码-问题出现的场景
对参数的安全判断、验权等等代码我就不放上来了,这里采用了jpa方式查询,直接上关键代码:
代码语言:javascript复制public List<KLine> findAllKLine(Long startTime, Long endTime) {
// 创建查询标准对象
Criteria criteria = new Criteria();
// 判断参数是否存在
if (!ObjectUtils.isEmpty(from) || !ObjectUtils.isEmpty(to)) {
// createTime为MongoDB文档中的一个时间类型的键值对,格式为“2018-05-11T05:58:51.122Z”
criteria = criteria.and("createTime");
// 开始时间
if (!ObjectUtils.isEmpty(startTime)) {
// 将时间戳转换为date类型
criteria.gte(new Date(startTime));
}
// 结束时间
if (!ObjectUtils.isEmpty(endTime)) {
criteria.lte(new Date(endTime));
}
}
// 封闭
Query query = Query.query(criteria);
// 排序规则:排序升序
query.with(Sort.by(
Sort.Order.asc("ts")
));
// 开始查询
List<KLine> list = mongoTemplate.find(query,KLine.class,"kline_" xxx);
// 直接返回,不做内容安全判断了
return list;
}
一套下来是那么的丝滑!看着没问题,调用一下
因为modb数据库已经有大量的数据,只需要在数据库中选择两个时间段传递过来测试就行了,也就是这一套操作下来出去的问题: 我选择了一段时间,期待着他给我反馈这一段时间的数据,程序确实返回了数据,但是仔细去看这些数据就会发现时间对不上。 数据对不上,很痛苦,终究还是不太丝滑。
三、解决
我开始反复对时间戳进行修改,来确认是否是数据的问题,刚好我的同事(阿贵)过来了,他看了代码也感觉是非常奇怪,于是便回到工位去查询资料,而我也接着对线这个问题,直到同事(阿贵)他发来了一个图片:
重点:只要涉及到mongo的增删改查,它都会默认将时间-8,再进行操作。我立刻查看程序返回数据的时间,确实和我想要的数据时间相差8个小时,确实马虎了,没有注意到数据内容。
那么知道了问题在哪,就很好解决了:
代码语言:javascript复制public static final int TIME_PLUS_8_HOUR_MS = 28800000;
public List<KLine> findAllKLine(Long startTime, Long endTime) {
// 创建查询标准对象
Criteria criteria = new Criteria();
// 判断参数是否存在
if (!ObjectUtils.isEmpty(from) || !ObjectUtils.isEmpty(to)) {
// createTime为MongoDB文档中的一个时间类型的键值对,格式为“2018-05-11T05:58:51.122Z”
criteria = criteria.and("createTime");
// 开始时间
if (!ObjectUtils.isEmpty(startTime)) {
// 时间戳 8个小时
// 将时间戳转换为date类型
criteria.gte(new Date(startTime TIME_PLUS_8_HOUR_MS));
}
// 结束时间
if (!ObjectUtils.isEmpty(endTime)) {
criteria.lte(new Date(endTime TIME_PLUS_8_HOUR_MS));
}
}
// 封闭
Query query = Query.query(criteria);
// 排序规则:排序升序
query.with(Sort.by(
Sort.Order.asc("ts")
));
// 开始查询
List<KLine> list = mongoTemplate.find(query,KLine.class,"kline_" xxx);
// 直接返回,不做内容安全判断了
return list;
}
好,记录完毕,感谢阿贵,愿你我一直在努力进步!