如何过滤比较日期时间 属性 与另一个加时间跨度值的子集合?
How can I filter child collection comparing datetime property with another one plus timespan value?
比如这个
var items = await database.GetCollection<CollectionItem>("collection").AsQueryable()
.Where(r => r.SubCollection.Any(i =>
i.DateTimeProp < i.OtherDateTimeProp + TimeSpan.FromMinutes(59))
.ToListAsync();
给我 mongo 驱动程序错误,不支持的过滤器:
({}{DateTimeProp} < {}{OtherDateTimeProp} + 00:59:00)
有什么办法吗?谢谢!
对于 DateTime,您应该使用 SQL-Functions
中的方法
它实际上计算给定时间间隔内日期之间的差异
这可以像
一样使用
SqlFunctions.DateDiff("minutes", i.DateTimeProp , i.OtherDateTimeProp) < 59
当然还需要MongoDB-EF Provider的支持,但是应该实现了。
你可以这样做:
var otherDateTime = new DateTime(2019, 12, 16, 16, 33, 20);
var filter = Builders<RootObject>.Filter.Gt(x => x.DataTimeProp, otherDateTime.AddMinutes(59));
var result = (await context.MyCollection.FindAsync(filter)).ToList();
mongo 驱动程序对日期时间范围的支持非常薄弱。我使用自定义 class 将 ticks
和 isodate
存储在 mongodb 的单独属性中,因此我能够像这样进行范围查询:
var result = collection.AsQueryable()
.SelectMany(t =>
t.SubCollection,
(t, s) => new
{
isMatch = s.DateTimeProp.Ticks < s.OtherDateTimeProp.Ticks + TimeSpan.FromMinutes(59).Ticks,
t.ID
})
.Where(x => x.isMatch)
.Select(x => x.ID)
.ToList();
自定义日期class:
public class Date
{
private long ticks = 0;
private DateTime date = new DateTime();
public long Ticks
{
get => ticks;
set { date = new DateTime(value); ticks = value; }
}
public DateTime DateTime
{
get => date;
set { date = value; ticks = value.Ticks; }
}
public static implicit operator Date(DateTime dt)
{
return new Date { DateTime = dt };
}
public static implicit operator DateTime(Date dt)
{
if (dt == null) throw new NullReferenceException("The [Date] instance is Null!");
return new DateTime(dt.Ticks);
}
}
这是一个完整的测试程序:
using MongoDB.Entities;
using MongoDB.Entities.Core;
using System;
using System.Linq;
namespace Whosebug
{
public class Test : Entity
{
public string Name { get; set; }
public SubTest[] SubCollection { get; set; }
}
public class SubTest
{
public Date DateTimeProp { get; set; }
public Date OtherDateTimeProp { get; set; }
}
public class Date
{
private long ticks = 0;
private DateTime date = new DateTime();
public long Ticks
{
get => ticks;
set { date = new DateTime(value); ticks = value; }
}
public DateTime DateTime
{
get => date;
set { date = value; ticks = value.Ticks; }
}
public static implicit operator Date(DateTime dt)
{
return new Date { DateTime = dt };
}
public static implicit operator DateTime(Date dt)
{
if (dt == null) throw new NullReferenceException("The [Date] instance is Null!");
return new DateTime(dt.Ticks);
}
}
public class Program
{
private static void Main(string[] args)
{
new DB("test", "localhost");
(new[] {
new Test{
Name = "one",
SubCollection = new[]{
new SubTest{ OtherDateTimeProp = DateTime.UtcNow, DateTimeProp = DateTime.UtcNow.AddMinutes(50)}, // should match
new SubTest{ OtherDateTimeProp = DateTime.UtcNow, DateTimeProp = DateTime.UtcNow.AddMinutes(60)}
}
},
new Test{
Name = "two",
SubCollection = new[]{
new SubTest{ OtherDateTimeProp = DateTime.UtcNow, DateTimeProp = DateTime.UtcNow.AddMinutes(60)},
new SubTest{ OtherDateTimeProp = DateTime.UtcNow, DateTimeProp = DateTime.UtcNow.AddMinutes(60)}
}
}
}).Save();
var result = DB.Queryable<Test>() // use collection.AsQueryable() for official driver
.SelectMany(t =>
t.SubCollection,
(t, s) => new
{
isMatch = s.DateTimeProp.Ticks < s.OtherDateTimeProp.Ticks + TimeSpan.FromMinutes(59).Ticks,
t.ID,
t.Name
})
.Where(x => x.isMatch)
.Select(x => x.ID)
.ToList();
}
}
}
比如这个
var items = await database.GetCollection<CollectionItem>("collection").AsQueryable()
.Where(r => r.SubCollection.Any(i =>
i.DateTimeProp < i.OtherDateTimeProp + TimeSpan.FromMinutes(59))
.ToListAsync();
给我 mongo 驱动程序错误,不支持的过滤器:
({}{DateTimeProp} < {}{OtherDateTimeProp} + 00:59:00)
有什么办法吗?谢谢!
对于 DateTime,您应该使用 SQL-Functions
中的方法它实际上计算给定时间间隔内日期之间的差异 这可以像
一样使用 SqlFunctions.DateDiff("minutes", i.DateTimeProp , i.OtherDateTimeProp) < 59
当然还需要MongoDB-EF Provider的支持,但是应该实现了。
你可以这样做:
var otherDateTime = new DateTime(2019, 12, 16, 16, 33, 20);
var filter = Builders<RootObject>.Filter.Gt(x => x.DataTimeProp, otherDateTime.AddMinutes(59));
var result = (await context.MyCollection.FindAsync(filter)).ToList();
mongo 驱动程序对日期时间范围的支持非常薄弱。我使用自定义 class 将 ticks
和 isodate
存储在 mongodb 的单独属性中,因此我能够像这样进行范围查询:
var result = collection.AsQueryable()
.SelectMany(t =>
t.SubCollection,
(t, s) => new
{
isMatch = s.DateTimeProp.Ticks < s.OtherDateTimeProp.Ticks + TimeSpan.FromMinutes(59).Ticks,
t.ID
})
.Where(x => x.isMatch)
.Select(x => x.ID)
.ToList();
自定义日期class:
public class Date
{
private long ticks = 0;
private DateTime date = new DateTime();
public long Ticks
{
get => ticks;
set { date = new DateTime(value); ticks = value; }
}
public DateTime DateTime
{
get => date;
set { date = value; ticks = value.Ticks; }
}
public static implicit operator Date(DateTime dt)
{
return new Date { DateTime = dt };
}
public static implicit operator DateTime(Date dt)
{
if (dt == null) throw new NullReferenceException("The [Date] instance is Null!");
return new DateTime(dt.Ticks);
}
}
这是一个完整的测试程序:
using MongoDB.Entities;
using MongoDB.Entities.Core;
using System;
using System.Linq;
namespace Whosebug
{
public class Test : Entity
{
public string Name { get; set; }
public SubTest[] SubCollection { get; set; }
}
public class SubTest
{
public Date DateTimeProp { get; set; }
public Date OtherDateTimeProp { get; set; }
}
public class Date
{
private long ticks = 0;
private DateTime date = new DateTime();
public long Ticks
{
get => ticks;
set { date = new DateTime(value); ticks = value; }
}
public DateTime DateTime
{
get => date;
set { date = value; ticks = value.Ticks; }
}
public static implicit operator Date(DateTime dt)
{
return new Date { DateTime = dt };
}
public static implicit operator DateTime(Date dt)
{
if (dt == null) throw new NullReferenceException("The [Date] instance is Null!");
return new DateTime(dt.Ticks);
}
}
public class Program
{
private static void Main(string[] args)
{
new DB("test", "localhost");
(new[] {
new Test{
Name = "one",
SubCollection = new[]{
new SubTest{ OtherDateTimeProp = DateTime.UtcNow, DateTimeProp = DateTime.UtcNow.AddMinutes(50)}, // should match
new SubTest{ OtherDateTimeProp = DateTime.UtcNow, DateTimeProp = DateTime.UtcNow.AddMinutes(60)}
}
},
new Test{
Name = "two",
SubCollection = new[]{
new SubTest{ OtherDateTimeProp = DateTime.UtcNow, DateTimeProp = DateTime.UtcNow.AddMinutes(60)},
new SubTest{ OtherDateTimeProp = DateTime.UtcNow, DateTimeProp = DateTime.UtcNow.AddMinutes(60)}
}
}
}).Save();
var result = DB.Queryable<Test>() // use collection.AsQueryable() for official driver
.SelectMany(t =>
t.SubCollection,
(t, s) => new
{
isMatch = s.DateTimeProp.Ticks < s.OtherDateTimeProp.Ticks + TimeSpan.FromMinutes(59).Ticks,
t.ID,
t.Name
})
.Where(x => x.isMatch)
.Select(x => x.ID)
.ToList();
}
}
}