MongoTemplate对带时间数据的操作

文章目录

    • 插入一些数据看看
    • 按日期查询一个
    • 按时间范围查询
    • 改变查询方式

java8 Springboot

插入一些数据看看

定义了一个TimeMongo类,里面设置了不同类型的时间,作为实体类。

@Id
String id;
Date date;
LocalDateTime localDateTime;
LocalDate localDate;
LocalTime localTime;
String string;

public TimeMongo(String id, Date date,  LocalDate localDate, LocalTime localTime, String string) {
        this.id = id;
        this.date = date;
        this.localDateTime = LocalDateTime.of(localDate,localTime);
        this.localDate = localDate;
        this.localTime = localTime;
        this.string = string;
    }

插入的方法

public void insert(List<TimeMongo> timeList) {
        mongoTemplate.insert(timeList,"timeList");
}

随便插入一些实例

List<TimeMongo> timeMongos = Arrays.asList(
                new TimeMongo("1", getDate(2020, 1, 2),LocalDate.of(2020, 1, 2), LocalTime.now(), "2020-01-02"),
                new TimeMongo("2", getDate(2020, 2, 6), LocalDate.of(2020, 2, 6), LocalTime.now(), "2020-02-06"),
                new TimeMongo("3", getDate(2020, 2, 15), LocalDate.of(2020, 2, 15), LocalTime.now(), "2020-02-15"),
                new TimeMongo("4", getDate(2020, 3, 20), LocalDate.of(2020, 3, 20), LocalTime.now(), "2020-03-20"),
                new TimeMongo("5", getDate(2020, 3, 21), LocalDate.of(2020, 3, 21), LocalTime.now(), "2020-03-21"),
                new TimeMongo("6", getDate(2020, 4, 2), LocalDate.of(2020, 4, 2), LocalTime.now(), "2020-04-02"),
                new TimeMongo("7", getDate(2020, 4, 6), LocalDate.of(2020, 4, 6), LocalTime.now(), "2020-04-06")
        );
        mongoTime.insert(timeMongos);
private Date getDate(int year, int month, int day) {
        Calendar ca = Calendar.getInstance();
        ca.set(year, month - 1, day);
        return ca.getTime();
    }

运行后查看mongo库,这时,我发现各种类型的时间在mongo里存的都是同样的系统时间格式

{
	"_id" : "7",
	"date" : ISODate("2020-04-06T13:23:37.691+08:00"),
	"localDateTime" : ISODate("2020-04-06T13:23:37.691+08:00"),
	"localDate" : ISODate("2020-04-06T00:00:00.000+08:00"),
	"localTime" : ISODate("2020-03-16T13:23:37.691+08:00"),
	"string" : "2020-04-06",
	"_class" : "zs.entity.mongoPo.TimeMongo"
}

按日期查询一个

public List<TimeMongo> select(TimeMongo timeMongo) {
        Query query = new Query(Criteria.byExample(timeMongo));
        return mongoTemplate.find(query, TimeMongo.class, "timeList");
    }

按照localDate查询

TimeMongo t=new TimeMongo();
t.setLocalDate(LocalDate.of(2020, 4, 2));
mongoTime.select(t).forEach(timeMongo -> System.out.println(timeMongo.toString()));

查询结果
TimeMongo{id=‘6’, date=Thu Apr 02 13:23:37 CST 2020, localDateTime=2020-04-02T13:23:37.691, localDate=2020-04-02, localTime=13:23:37.691, string=‘2020-04-02’}
没毛病,就是我想要的结果

按照Date查询
最后没查出结果,至于原因嘛,localDate创建时时间默认都是0,Date时间默认时现在,时间不一样,所以没查出来,查询怎么忽略时间只看日期,写下面。

按时间范围查询

业务中最常用到的是取两个日期之间的数据,例如:2020-02-05到2020-05-20之间注册的用户
先试试直男查法

public void select(String startTime, String endTime) {
        Query query1 = new Query(Criteria.where("date").gte(startTime).andOperator(Criteria.where("date").lte(endTime)));
        mongoTemplate.find(query1, TimeMongo.class, "timeList").forEach(e -> System.out.println(e.toString()));
        System.out.println("-------------------------");

        Query query2 = new Query(Criteria.where("localDateTime").gte(startTime).andOperator(Criteria.where("localDateTime").lte(endTime)));
        mongoTemplate.find(query2, TimeMongo.class, "timeList").forEach(e -> System.out.println(e.toString()));
        System.out.println("-------------------------");

        Query query3 = new Query(Criteria.where("localDate").gte(startTime).andOperator(Criteria.where("localDate").lte(endTime)));
        mongoTemplate.find(query3, TimeMongo.class, "timeList").forEach(e -> System.out.println(e.toString()));
        System.out.println("-------------------------");

        Query query4 = new Query(Criteria.where("string").gte(startTime).andOperator(Criteria.where("string").lte(endTime)));
        mongoTemplate.find(query4, TimeMongo.class, "timeList").forEach(e -> System.out.println(e.toString()));
        System.out.println("-------------------------");
    }

按2020-03-20格式查询结果,最后一个string有结果,其他都没有。
按2020-03-20T00:00:00.000+08:00,结果差不多,其他都没有,只是单纯的字符串比较

把startTime, endTime改成其他格式试试,这下上面三种时间类型都可以查出,原理还是把各种日期类型统一成一种,转化成固定的字符串格式,最后比较字符串,比较时还是比较日期和时间,有两种方法可以解决需求,不需要时间的字段存的时候就只存日期,或者改变查询方式

改变查询方式

mongo查询语句长这个样子

db.timeList.find({
    "localDate":{
        "$gte" : ISODate("2020-02-06T00:00:00.000+08:00") }, 
        "$and" : [{ "localDate" : { "$lte" : ISODate("2020-03-21T00:00:00.000+08:00") } 
        }]
})

ISODate这个鬼在代码中怎么表示,我也不知道,代码中的各种时间类型存进去都变成了统一的系统时间类型。
但要查询时间,我找到了更灵活的方式,就是把原来的时间变成指定格式字符串再进行筛选
mongo已经提供相应的转格式方式dateToString

db.timeList.aggregate([
    {
        "$project": {
            "date": {
                "$dateToString": {
                    "format": "%Y-%m-%d",
                    "date": "$localDateTime"
                }
            }
        }
    },
    {
        "$match": {
            "localDateTime": {
                "$gte": "2020-02-06"
            },
            "$and": [
                {
                    "localDateTime": {
                        "$lte": "2020-03-21"
                    }
                }
            ]
        }
    }
])

执行语句有了,到代码里找对应的方法,一般会有对应的。
project类似sql语句select后面那一串,选择 字段 as 字段名,只是执行顺序不一样,你得先起一个别名然后根据别名筛选,sql先把后面一堆执行完,最后执行select的东西。

public void select(String startTime,String endTime){
        AggregationOperation project=Aggregation.project().and("localDateTime")
                .dateAsFormattedString("%Y-%m-%d").as("date");
        AggregationOperation match= Aggregation.match(Criteria.where("date").gte(startTime)
                .andOperator(Criteria.where("date").lte(endTime)));
        Aggregation aggregation=Aggregation.newAggregation(project,match);
        
        List<Document>documentList=mongoTemplate.aggregate(aggregation,"timeList",Document.class)
                .getMappedResults();
        documentList.forEach(document -> System.out.println(document.toJson()));
    }

用聚和查询就不用手动处理时间格式的字符串,同时,这样可以关联其他的集合和做更丰富的操作。

你可能感兴趣的:(NoSQL)