如何使用 DocumentDb 查询 DateTimeOffset
How to query DateTimeOffset with DocumentDb
假设我将记录插入到以下模型的 Azure DocumentDb 中:
public class Message
{
[JsonProperty(PropertyName = "tid")]
public string Id { get; set; }
[JsonProperty(PropertyName = "start")]
public DateTimeOffset StartAt { get; set; }
}
它们都自动存储为字符串。我希望能够查询StartAt
,所以我在上面添加了一个RngeIndex。我使用 Azure 门户验证索引是否正常工作。
除此之外,我加载了 DocumentDb .NET SDK 并尝试以下查询:
var since = DateTimeOffset.UtcNow.Subtract(duration);
return Client.CreateDocumentQuery<T>(Collection.DocumentsLink)
.Where(m => m.AtStart > since)
.AsEnumerable();
但是我收到错误
[DocumentQueryException: Constant of type 'System.DateTimeOffset' is not supported.]
Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitConstant(ConstantExpression inputExpression) +3204
Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitBinary(BinaryExpression inputExpression, TranslationContext context) +364
Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitBinary(BinaryExpression inputExpression, TranslationContext context) +349
Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitScalarLambda(Expression inputExpression, TranslationContext context) +230
Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitWhere(ReadOnlyCollection`1 arguments, TranslationContext context) +55
Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitMethodCall(MethodCallExpression inputExpression, TranslationContext context) +799
Microsoft.Azure.Documents.Linq.ExpressionToSql.Translate(Expression inputExpression, TranslationContext context) +91
Microsoft.Azure.Documents.Linq.ExpressionToSql.TranslateQuery(Expression inputExpression) +46
Microsoft.Azure.Documents.Linq.SQLTranslator.TranslateQuery(Expression inputExpression) +20
Microsoft.Azure.Documents.Linq.<ExecuteAllAsync>d__7.MoveNext() +177
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +179
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +66
System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) +30
Microsoft.Azure.Documents.Linq.<GetEnumeratorTAsync>d__10.MoveNext() +632
有没有办法在不改变底层模型的情况下执行类型安全的查询?
您可以对日期执行范围查询,但不能作为 "type-safe" 查询。
这是因为 DocumentDB 没有日期时间数据类型。相反,DocumentDB 严格遵守支持的数据类型(字符串、数字、布尔值、数组、对象和空值)的 JSON 规范。因此,当您尝试使用 LINQ 提供程序直接查询 DateTimeOffset 时,会出现异常 Constant of type 'System.DateTimeOffset' is not supported
。
默认情况下,DocumentDB Client SDK 将日期时间对象属性序列化为 ISO 8601 格式的字符串,如下所示:2014-09-15T23:14:25.7251173Z
。在字符串上添加范围索引将允许您对日期执行字符串范围查询。您可以将 var since = DateTimeOffset.UtcNow.Subtract(duration);
序列化为 ISO 8601 字符串以在您的代码片段中执行查询。
查看此 blog post 以更深入地讨论如何使用日期。请注意,该博客略有过时,因为自该博客 post 最初创作以来就添加了对字符串范围索引和查询的支持。
假设我将记录插入到以下模型的 Azure DocumentDb 中:
public class Message
{
[JsonProperty(PropertyName = "tid")]
public string Id { get; set; }
[JsonProperty(PropertyName = "start")]
public DateTimeOffset StartAt { get; set; }
}
它们都自动存储为字符串。我希望能够查询StartAt
,所以我在上面添加了一个RngeIndex。我使用 Azure 门户验证索引是否正常工作。
除此之外,我加载了 DocumentDb .NET SDK 并尝试以下查询:
var since = DateTimeOffset.UtcNow.Subtract(duration);
return Client.CreateDocumentQuery<T>(Collection.DocumentsLink)
.Where(m => m.AtStart > since)
.AsEnumerable();
但是我收到错误
[DocumentQueryException: Constant of type 'System.DateTimeOffset' is not supported.]
Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitConstant(ConstantExpression inputExpression) +3204
Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitBinary(BinaryExpression inputExpression, TranslationContext context) +364
Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitBinary(BinaryExpression inputExpression, TranslationContext context) +349
Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitScalarLambda(Expression inputExpression, TranslationContext context) +230
Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitWhere(ReadOnlyCollection`1 arguments, TranslationContext context) +55
Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitMethodCall(MethodCallExpression inputExpression, TranslationContext context) +799
Microsoft.Azure.Documents.Linq.ExpressionToSql.Translate(Expression inputExpression, TranslationContext context) +91
Microsoft.Azure.Documents.Linq.ExpressionToSql.TranslateQuery(Expression inputExpression) +46
Microsoft.Azure.Documents.Linq.SQLTranslator.TranslateQuery(Expression inputExpression) +20
Microsoft.Azure.Documents.Linq.<ExecuteAllAsync>d__7.MoveNext() +177
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +179
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +66
System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) +30
Microsoft.Azure.Documents.Linq.<GetEnumeratorTAsync>d__10.MoveNext() +632
有没有办法在不改变底层模型的情况下执行类型安全的查询?
您可以对日期执行范围查询,但不能作为 "type-safe" 查询。
这是因为 DocumentDB 没有日期时间数据类型。相反,DocumentDB 严格遵守支持的数据类型(字符串、数字、布尔值、数组、对象和空值)的 JSON 规范。因此,当您尝试使用 LINQ 提供程序直接查询 DateTimeOffset 时,会出现异常 Constant of type 'System.DateTimeOffset' is not supported
。
默认情况下,DocumentDB Client SDK 将日期时间对象属性序列化为 ISO 8601 格式的字符串,如下所示:2014-09-15T23:14:25.7251173Z
。在字符串上添加范围索引将允许您对日期执行字符串范围查询。您可以将 var since = DateTimeOffset.UtcNow.Subtract(duration);
序列化为 ISO 8601 字符串以在您的代码片段中执行查询。
查看此 blog post 以更深入地讨论如何使用日期。请注意,该博客略有过时,因为自该博客 post 最初创作以来就添加了对字符串范围索引和查询的支持。