如何使用DocumentDb查询DateTimeOffset

时间:2015-11-13 15:16:34

标签: azure-cosmosdb

假设我将记录插入以下模型的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

有没有办法在不更改基础模型的情况下执行类型安全的查询?

1 个答案:

答案 0 :(得分:6)

您可以对日期执行范围查询,但不能作为“类型安全”查询。

这是因为DocumentDB没有日期时间数据类型。相反,DocumentDB严格遵守支持的数据类型(String,Number,Boolean,Array,Object和Null)的JSON规范。因此,当尝试使用LINQ Provider直接在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,了解有关使用日期的更深入讨论。请注意,博客稍微过时,因为自博客文章最初创作以来已添加对字符串范围索引和查询的支持。