[英]Search for overlapping date ranges
I have product collection with a list of date ranges that represent dates when products are rented. 我有一个带有日期范围列表的产品集合,这些日期范围表示产品租用的日期。 So it looks something like this:
所以看起来像这样:
"product" : {
...
"RentalPeriods" : [
{
"From" : ISODate("2017-02-11T23:00:00.000Z"),
"To" : ISODate("2017-02-12T23:00:00.000Z")
},
{
"From" : ISODate("2017-10-09T23:00:00.000Z"),
"To" : ISODate("2017-10-21T23:00:00.000Z")
}
]
...
}
I want to create query that will go through all products and to return only products that can be rented for provided date range. 我想创建查询所有产品的查询,并只返回在指定日期范围内可以租用的产品。 So if I provide something like:
因此,如果我提供以下信息:
RentalPeriod("2017-03-03", "2017-03-04") - it should return above product RentalPeriod(“ 2017-03-03”,“ 2017-03-04”)-应该返回以上产品
RentalPeriod("2017-02-03", "2017-02-14") - it should not return above product RentalPeriod(“ 2017-02-03”,“ 2017-02-14”)-它不应返回以上产品
We tried with LINQ expression, but we got Unsupported filter Exception. 我们尝试使用LINQ表达式,但是得到了不支持的过滤器异常。
So this is what we tried: 所以这是我们尝试的:
public Expression<Func<Product, bool>> IsSatisfied() =>
product => product.RentalPeriods.All(rentPeriod => !(_fromDate > rentPeriod.FromDate && _fromDate < rentPeriod.MaybeToDate.Value) &&
!(rentPeriod.FromDate > _fromDate && rentPeriod.FromDate < _toDate));
(Above query is partial, but I suppose it is clear what we tried). (以上查询是局部的,但我想很清楚我们尝试了什么)。
Is there any other way how we can achieve this? 还有其他方法可以实现这一目标吗?
Edit 13-12-2017 : 编辑13-12-2017 :
public class AvailabilityForRentalPeriodSpecification : ISpecification<Product>
{
private UtcDate _fromDate;
private UtcDate _toDate;
public AvailabilityForRentalPeriodSpecification(RentalPeriod rentalPeriod)
{
_fromDate = rentalPeriod.FromDate;
_toDate = rentalPeriod.MaybeToDate.Value;
}
public Expression<Func<Product, bool>> IsSatisfied() =>
product => product.RentalPeriods.All(rentPeriod => !(_fromDate > rentPeriod.FromDate && _fromDate < rentPeriod.MaybeToDate.Value) &&
!(rentPeriod.FromDate > _fromDate && rentPeriod.FromDate < _toDate));
}
This specification is used in DAO layer as: 该规范在DAO层中用作:
public IList<T> GetBy(ISpecification<T> specification)
=> _mongoCollection.Find(specification.IsSatisfied()).ToList();
Possible solution (that I'm trying to avoid) is to retrieve all products from DB and then to filter them in the code. 可能的解决方案(我试图避免)是从DB中检索所有产品,然后在代码中对其进行过滤。
I changed a query logic to use Any method instead of unsupported All method, so it looks like this now: 我将查询逻辑更改为使用Any方法而不是不受支持的All方法,因此现在看起来像这样:
public Expression<Func<Product, bool>> IsSatisfied() =>
product => !product.RentalPeriods.Any(dbRentalPeriod => _fromDate >= dbRentalPeriod.FromDate && _fromDate <= dbRentalPeriod.ToDate ||
_toDate >= dbRentalPeriod.FromDate && _toDate <= dbRentalPeriod.ToDate ||
dbRentalPeriod.FromDate >= _fromDate && dbRentalPeriod.ToDate <= _toDate);
Another problem was using Maybe struct for ToDate (rentPeriod.MaybeToDate.Value), which is resolved by creating internal DateTime field next to the MaybeToDate field. 另一个问题是对ToDate使用了Maybe结构(rentPeriod.MaybeToDate.Value),可以通过在MaybeToDate字段旁边创建内部DateTime字段来解决。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.