因此,如标题所示,我的MongoDB数据库中有以下示例文档:
{"_id":{"$oid":"5fcf541b466a3d10f55f8241"}, "dateOfBirth":"1992-11-02T12:05:17"}
正如您所看到的,日期存储为String,而不是ISODate对象。据我所知,MongoDB应该仍然能够将其作为Date进行处理和查询。(来源(
因此,我试图用JDBC在我的java应用程序中以以下方式查询它:
java.util.Date queryDate = new GregorianCalendar(1980, Calendar.JANUARY, 1).getTime();
Bson query = Filters.gte("dateOfBirth", queryDate);
FindIterable<Document> result = collection.find(query);
然而,这是行不通的。我的想法是,如果我传入java.util.Date,那么Filters.gte((方法就会知道我的意思是查询Date,它将在MongoDB中按预期工作。但是,我得到0个匹配项。
我还试着在queryDate上放一个格式化程序(之前有不同的用途(:
DateFormat dformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Bson query = Filters.gte("dateOfBirth", dformat.format(queryDate));
然而,这导致Filters.gte((根据字符串比较将其查询为字符串,因此大致按字母顺序排列。这让我最初认为,最初的java.util.Date版本确实/应该知道,当时我查询的是Date,而不是String,它只是不知何故未能将数据库中的日期类型转换为日期类型?我不确定它应该如何工作。
我知道这是一种特殊情况下的用法,我真的应该在mongoDB中插入日期作为ISODate,但在我现在的特殊情况下,这不是一种选择。
如果我使用JDBC,有没有一种方法可以查询存储在MongoDB中的字符串日期?
次要的一点:您正在使用MongoDB的Java连接器。JDBC驱动程序适用于使用SQL查询语言的关系数据库。因此,我在您的问题中将JDBC
标记更改为Java
将日期作为字符串使用
关于文档中的日期时间格式:由于您使用的格式以及它存储为字符串,因此在运行查询时可以使用字符串比较。词汇排序将确保字符串比较等效于日期时间比较。这是你链接到的问题中的代码正在使用的内容。
显然,如果您有任何以其他字符串格式存储的数据,例如";dd-MM-yyyy";,其中字符串排序与日期时间排序不匹配。
但是,您应该避免使用旧的和有问题的Java
Date
和Calendar
类。相反,请使用现代的java.time
类。更多背景信息请点击此处。
在您的情况下,您的文档存储的日期时间数据没有任何时区或偏移信息。您可以使用java.time.LocalDateTime
。单词";本地";在这个名称中实际上意味着";没有特定的地点或时区"-这与Mongo文档中的内容相匹配。
Java导入:
import java.time.LocalDateTime;
import java.time.Month;
import java.time.format.DateTimeFormatter;
本地日期时间示例:
LocalDateTime ldt = LocalDateTime.of(1980, Month.JANUARY, 1, 0, 0);
DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;
String s = ldt.format(dtf); // "1980-01-01T00:00:00"
使用日期作为对象
如果您想在查询中直接使用JavaLocalDate
对象,而不是使用字符串比较,您可以使用投影在查询结果中创建日期对象,然后在过滤器中直接使用JavaLocalDate
对象:
Bson resultsWithDate = Aggregates.project(Projections.fields(
Projections.include("dateOfBirth"),
Projections.computed("birthDate", Projections.computed("$toDate", "$dateOfBirth"))
));
上面的投影为每个检索到的文档添加了一个新的dateOfBirth
字段,并通过$toDate
运算符填充它。
然后我们可以应用我们的过滤器:
collection.aggregate(
Arrays.asList(
resultsWithDate,
Aggregates.match(Filters.gte("birthDate", ldt)))
).forEach(printConsumer);
过滤器现在使用上面的ldt
对象。
我使用以下助手方法在控制台中将每个结果文档打印为JSON字符串:
Consumer<Document> printConsumer = (final Document document) -> {
System.out.println(document.toJson());
};
可能有一种更紧凑或更高效的方法来构建这个MongoDB聚合——我不是Mongo的普通用户。
此外,最后要注意的是:我使用的Mongo$toDate
运算符没有指定时区,因此它默认为祖鲁时间(UT时区(,如下面的示例输出所示:
{
"_id": {
"$oid": "5fcf541b466a3d10f55f8241"
},
"dateOfBirth": "1992-11-02T12:05:17",
"birthDate": {
"$date": "1992-11-02T12:05:17Z"
}
}