DocumentDB 如何在_TS 上进行LINQ 查询?

DocumentDB how to LINQ query on _TS?

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

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

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

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

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

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

这没有结果,当我看到执行的查询时,它有一个 select 查询:

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

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

您的查询有几个问题。在您的第一个查询中,您正在比较 "Ticks"(百万分之一秒 - see here) to the _ts value which will most likely return all the documents in your collection because the _ts value is a POSIX (Unix) time measured in seconds see here。它们也不基于同一纪元。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 值或 TimeStamp 值。

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

    // 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 并通过 TimeStamp 字段公开它。根据 DocRepo 返回的类型,您可以做几件事。如果它是默认的文档类型,您可以创建一个新的 class 并像这样从文档类型继承:

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

如果是您自己的自定义 class,则只需将 _ts 字段添加到您的 class。无论哪种方式,如果 _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;
            }
        }

希望对您有所帮助。