mongodb按天查询数量

2020-05-15  本文已影响0人  我已不是少年郎

1、引言

最近做报表,日志都是存入mongodb,所以需要从mongodb统计查询。

需求:
1、按天查询当天日志条数。
2、返回当天日期和条数2个字段。

2、填坑关键点

2.1、时区问题

ISODate为0时区,查询时需要加入时区"timezone" : "Asia/Shanghai",否则凌晨8点以前的数据会归入前一天的日期。

3、解决过程

3.1、插入的文档格式

{
    "_id" : "1b21f6ebf1814b1f853d31d912648956",
    "createTime" : ISODate("2020-04-15T14:40:24.000+08:00")
}

3.2、插入的java代码字段

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.Date;

@Data
@Document(collection = "deviceLog")
public class DeviceLog {
    @Id
    private String logId;
    private Date createTime;
}

3.3、查询脚本

db.deviceLog.aggregate([
    { "$project" : { "createTime" : 1, "name" : { "$dateToString" : { "format" : "%Y-%m-%d", "date" : "$createTime" ,"timezone" : "Asia/Shanghai"}}}},
    { "$group" : { "_id" : "$name", "value" : { "$sum" : 1}}},
    { "$project" : { "value" : 1, "name" : "$_id"}},
    { "$sort" : { "name" : 1}}
])

3.4、查询结果

{
    "_id" : "2020-04-15",
    "value" : 3.0,
    "name" : "2020-04-15"
}

3.5、查询java代码

        String startDay = "2020-04-01";
        String endDay = "2020-04-21";

        //将字符日期转java.util.Date,自行转换即可
        Date startDate = DateUtils.stringToDate(startDay, DateUtils.DATE_PATTERN);
        Date endDate = DateUtils.stringToDate(endDay, DateUtils.DATE_PATTERN);

        Criteria whereCri = new Criteria();
        whereCri.and("createTime").gte(startDate).lte(endDate);

        Aggregation agg = Aggregation.newAggregation(
                // 匹配查询
                Aggregation.match(whereCri),
                // 设置时区,返回参数
                Aggregation.project("createTime").andExpression(
                        "{$dateToString:{format:'%Y-%m-%d',date:'$createTime',timezone: 'Asia/Shanghai'}}")
                        .as("name"),
                // 按条件分组
                Aggregation.group("name").count().as("value"),
                // 返回参数2
                Aggregation.project("value").and("_id").as("name"),
                //排序
                Aggregation.sort(Sort.Direction.ASC, "name")
        );

        log.error("agg:{}", agg.toString());

        AggregationResults<NameValueEntity> dataResult = mongoTemplate.aggregate(agg, DeviceLog.class, NameValueEntity.class);
        List<NameValueEntity> data = dataResult.getMappedResults();
        log.error("size:{} data:{}", data.size(), data.toArray());

NameValueEntity.java

@Data
public class NameValueEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    private String name;
    private Long value;
}
上一篇下一篇

猜你喜欢

热点阅读