DocumentDB 如何对_TS进行 LINQ 查询

本文关键字:进行 LINQ 查询 TS DocumentDB | 更新日期: 2023-09-27 18:34:38

我想查询文档上的更新时间戳_ts,以获取自一定时间以来未发生突变的文档。

当我在 Azure 门户中创建选择查询时,这有效:

SELECT TOP 10 c.id FROM c WHERE c._ts < 6.35909919217878E+17

奇怪的数字是使用日期时间对象创建的即时报价,见下文。

但是当我尝试通过 LINQ 创建它时,它不会这样做,因为您没有_ts,只有一个时间戳作为 DateTime 对象。当我尝试输入完整的日期时间对象以与时间戳进行比较时,它崩溃了,说它不支持它。所以我试试这个:

DocRepo.Get(x => x.Timestamp.Ticks < CloseDate.Ticks);

这没有任何结果,当我观察执行的查询时,它将其作为选择查询:

SELECT * FROM root WHERE root['"_ts'"]['"Ticks'"] < 6.35909943137688E+17

是否可以查询_ts时间戳,或者我是否必须有一个额外的 updateAt 字段才能执行此操作,这似乎是多余的。

DocumentDB 如何对_TS进行 LINQ 查询

您的查询有几个问题。 在第一个查询中,您将"Ticks"(一千万分之一秒 - 请参阅此处(与_ts值进行比较,该值很可能会返回集合中的所有文档,因为_ts值是以秒为单位的 POSIX (Unix( 时间,请参阅此处。它们也不是基于同一个时代。Unix 值从午夜 1,1,1970 开始,而 Ticks 从午夜 1,1,0001 开始 因此,_ts值将始终远小于 Ticks 值(更不用说 1,969 年了! 您需要将日期转换为其 Unix 时间值。您可以创建一个扩展方法来帮助您执行此操作:

    public static long ToUnixTime(this DateTime date)
    {
        var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        return (long)(date - epoch).TotalSeconds;
    }

至于 Linq 语句,您不能(不幸的是(将 DateTime 放入 Linq 查询中,因为 DateTime 值不会转换为 const(这是您遇到的错误(。因此,在这两种情况下,您都无法非常轻松地比较_ts值或时间戳值。

那怎么办?好吧,在查看 DocumentDB SDK 时,如果您查看时间戳的定义,您将看到以下内容:

    // Summary:
    //     Gets the last modified timestamp associated with the resource.
    [JsonConverter(typeof(UnixDateTimeConverter))]
    [JsonProperty(PropertyName = "_ts")]
    public virtual DateTime Timestamp { get; internal set; }

因此,默认情况下,SDK 会将_ts值转换为 DateTime,并通过时间戳字段公开它。 您可以做几件事,具体取决于您的 DocRepo 返回的类型。如果它是默认的文档类型,则可以创建一个新类并从文档类型继承,如下所示:

public class MyDocument : Document
{
    public long _ts
    {
        get; set;
    }
}

如果它是您自己的自定义类,则只需将_ts字段添加到您的类中即可。 无论哪种方式,如果存在_ts字段,DocumentDB 将填充该字段。 然后,如果添加 ToUnixTime 扩展方法,则可以像这样编写 Linq 查询:

DocRepo.Get(x => x._ts < CloseDate.ToUnixTime());

这可能不是一个优雅的解决方案,有人(希望(可能会想出一个更好的解决方案,但我已经验证了它适用于我自己的 DocumentDB 集合。

希望这有帮助。

这是我用来将 Unix 时间戳转换为我们可以在 C# 中轻松理解的 DateTime 格式:

  public DateTime TimeStamp
        {            
            get
            {
                return DateTimeOffset.FromUnixTimeSeconds(int.Parse(_ts)).DateTime;
            }
        }

希望这有帮助。