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;
}
}
希望对您有所帮助。
我想查询文档的更新时间戳 _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;
}
}
希望对您有所帮助。