记录使用mongoDB时遇到的有趣问题

2023-10-21 12:38:38 浏览数 (2)

一、前话

最近在开发金融类的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;
}

好,记录完毕,感谢阿贵,愿你我一直在努力进步!

0 人点赞