如何过滤比较日期时间 属性 与另一个加时间跨度值的子集合?

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

中的方法

https://docs.microsoft.com/en-us/dotnet/api/system.data.entity.sqlserver.sqlfunctions?view=entity-framework-6.2.0

它实际上计算给定时间间隔内日期之间的差异 这可以像

一样使用
    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 将 ticksisodate 存储在 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();
        }
    }
}