在spring mongodb中的两个字符串日期范围之间查找
Posted
技术标签:
【中文标题】在spring mongodb中的两个字符串日期范围之间查找【英文标题】:Find between two string date ranges in spring mongodb 【发布时间】:2020-05-30 07:32:24 【问题描述】:我有文档Person
喜欢
"_id":
"$oid": "5e44659dcd"
,
"record":
"Date_Of_Birth": "9/25/2018"
,
"_class": "com.example.entities.Birth"
Record
的类型为object
,Date_Of_Birth
的类型为String
,但Date
已存储在其中,我想执行查询以对其使用$gte 和$lte 操作。我正在使用弹簧数据 mongodb。似乎首先我必须使用 $dateFromString 将其转换为日期,但这似乎是我认为不需要的聚合。
下面是我目前创建的代码
Pageable pageable = PageRequest.of(page, size);
Query query = new Query(
Criteria
.where("record.Date_Of_Birth").gte(DateOperators.dateFromString(startDate).withFormat("mm/dd/yyyy"))
.andOperator(Criteria.where("record.Date_Of_Birth").lte(DateOperators.dateFromString(endDate).withFormat("mm/dd/yyyy"))
)).with(pageable);
生成这个查询
"record.Date_Of_Birth" : "$gte" : "value" : "dateString" : "9/25/2018", "format" : "mm/dd/yyyy", "$and" : [ "record.Date_Of_Birth" : "$lte" : "value" : "dateString" : "9/25/2018", "format" : "mm/dd/yyyy"]
而且根本不工作。有什么想法吗?
【问题讨论】:
为什么将日期值存储为字符串? 好吧...我现在别无选择。共享的 json 只是一个示例。实际的 json 是完全不同的,并且具有许多其他属性。我的应用程序将接收数据并将其存储在数据库中。所以我必须查询我目前拥有的东西。startDate
的类型和格式是什么?
@prasad_ 它是字符串类型,我传递的值是“9/25/2018”
您正在将字符串与日期进行比较。我怀疑您还需要将文档中的字段转换为日期,可能使用 $expr。
【参考方案1】:
$expr 允许在查询中使用聚合运算符。这将允许您将存储的值转换为日期,以便您可以进行苹果与苹果的比较。
db.collection.find(
$expr:
$gte: [
$dateFromString:
dateString: "$record.Date_Of_Birth",
format: "%m/%d/%Y",
timeZone: "EST5EDT",
$dateFromString:
dateString: "9/25/2018",
format: "%m/%d/%Y",
timeZone: "EST5EDT"
]
)
【讨论】:
它只匹配日期 "9/25/2018" 而不是大于那个日期的日期......比如 "9/26/2018" 等。可能是什么问题? 我把 $dateFromString 子句的顺序弄错了。现已修复 谢谢!我已经修改它以包含 $lte 以及 $and。【参考方案2】:由于文档字段Date_Of_Birth
的日期格式和输入的起始日期为字符串数据并且 格式为“MM/dd/yyyy”,如果出现以下情况,比较将不正确按原样使用。有不同的方法来处理这个问题。
将两种日期格式转换为“yyyy/MM/dd”字符串并进行比较或将两种日期转换为Date
对象并进行比较。请注意,示例代码显示了转换为 Date
对象的日期值的用法。
要转换find
查询的日期,过滤器将使用聚合日期或字符串转换运算符。 find
查询过滤器只能将聚合运算符与 $expr
运算符一起使用。
我无法清楚地将 $expr
与 MongoDB Spring-Data API 一起使用(我怀疑没有此类 API 可用于处理 $expr
,但可能有解决方法)。
清楚地运行查询的方法是使用聚合。以下是 Mongo Shell 和 Spring Data 版本。
db.persons.aggregate( [
$addFields:
matches:
$and: [
$gte: [
$dateFromString: dateString: "$record.Date_Of_Birth", format: "%m/%d/%Y" ,
ISODate("2018-09-24T00:00:00.00Z") // input from date
] ,
$lte: [
$dateFromString: dateString: "$record.Date_Of_Birth", format: "%m/%d/%Y" ,
ISODate("2018-11-10T00:00:00.00Z") // input to date
]
]
,
$match: matches: true
] )
Spring-Data Java 代码:
// Convert the String input dates to Date objects to be used in the query
String from = "9/24/2018";
String to = "11/10/2018";
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
Date fromDt = dateFormat.parse(from);
Date toDt = dateFormat.parse(to);
// Build and run the query
MongoOperations mongoOps = new MongoTemplate(MongoClients.create(), "test");
Aggregation agg = newAggregation(
project("record.Date_Of_Birth")
.and(Gte.valueOf(DateOperators.DateFromString.fromStringOf("record.Date_Of_Birth").withFormat("%m/%d/%Y"))
.greaterThanEqualToValue(fromDt))
.as("matches1")
.and(Lte.valueOf(DateOperators.DateFromString.fromStringOf("record.Date_Of_Birth").withFormat("%m/%d/%Y"))
.lessThanEqualToValue(toDt))
.as("matches2"),
match(where("matches1").is(true)),
match(where("matches2").is(true))
);
AggregationResults<Person> results = mongoOps.aggregate(agg, "persons", Person.class);
results.forEach(System.out::println);
【讨论】:
以上是关于在spring mongodb中的两个字符串日期范围之间查找的主要内容,如果未能解决你的问题,请参考以下文章
需要 mongodb 查询来检查日期是不是在存储在集合文档中的两个日期之间[重复]
如何使用 @Query 在日期 Spring 数据 MongoDB 之间进行选择
Spring数据mongodb存储库语法中的@Query注释