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()));
}
用聚和查询就不用手动处理时间格式的字符串,同时,这样可以关联其他的集合和做更丰富的操作。