在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 的类型为objectDate_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 查询来检查日期是不是在存储在集合文档中的两个日期之间[重复]

比较 MongoDB 中的两个日期字段

如何使用 @Query 在日期 Spring 数据 MongoDB 之间进行选择

Spring数据mongodb存储库语法中的@Query注释

转换以字符串格式存储的日期值并减去 mongodb 中的当前日期

Spring数据mongodb过滤字符串集合中的嵌套对象ID