在 Azure Cosmos DB for NoSQL 中处理日期

适用范围: NoSQL

Azure Cosmos DB for NoSQL 通过本机 JSON 数据模型提供架构灵活性和丰富的索引。 所有 Azure Cosmos DB 资源(包括数据库、容器、文档和存储过程)均作为 JSON 文档进行建模和存储。 为使代码可移植,JSON(及 Azure Cosmos DB)仅支持一小组基本类型:字符串、数字、布尔值、数组、对象和 Null。 但是,JSON 具有相当的灵活性,允许开发人员和框架使用这些基元并将其编写为对象或数组,以便表示更复杂的类型。

除了基本类型,许多应用程序还需要 DateTime 类型以表示日期和时间的类型。 本文介绍开发人员可如何使用 .NET SDK 在 Azure Cosmos DB 中存储、检索和查询日期。

存储 DateTime

Azure Cosmos DB 支持 JSON 类型,如字符串、数字、布尔值、null、数组和对象。 它不直接支持 DateTime 类型。 目前,API for NoSQL 不支持日期本地化。 因此,必须将日期和时间信息存储为字符串。 日期和时间字符串的建议格式为 yyyy-MM-ddTHH:mm:ss.fffffffZ,它遵循 ISO 8601 UTC 标准。 建议以 UTC 格式存储 Azure Cosmos DB 中的所有日期。 将日期字符串转换为此格式允许按字典顺序对日期进行排序。 如果存储非 UTC 日期,则必须在客户端处理相关逻辑。 若要将本地日期和时间值转换为 UTC,偏移量必须已知/存储为 JSON 中的属性,并且客户端可以使用偏移量来计算 UTC 日期和时间值。

仅当日期和时间字符串全部采用 UTC 格式时,才支持使用日期和时间字符串作为筛选器的范围查询。 GetCurrentDateTime 系统函数会返回以下格式的当前 UTC 日期和时间 ISO 8601 字符串值:yyyy-MM-ddTHH:mm:ss.fffffffZ

由于以下原因,大多数应用程序可以使用 DateTime 的默认字符串表示形式:

  • 字符串可以进行比较,而 DateTime 值的相对顺序在这些值转换为字符串时得以保留。
  • 此方法不需要进行 JSON 转换所需的任何自定义代码或属性。
  • 在 JSON 中存储的日期人工可读。
  • 这种方法可以利用索引执行快速查询。

例如,以下代码片段使用 .NET SDK 将 Order 对象存储为文档,该对象包含两个 DateTime 属性 - ShipDateOrderDate

public class Order
{
    [JsonProperty(PropertyName="id")]
    public string Id { get; set; }
    public DateTime OrderDate { get; set; }
    public DateTime ShipDate { get; set; }
    public double Total { get; set; }
}

await container.CreateItemAsync(
    new Order
    {
        Id = "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
        OrderDate = DateTime.UtcNow.AddDays(-30),
        ShipDate = DateTime.UtcNow.AddDays(-14),
        Total = 113.39
    });

本文档存储在以下结构中:

{
  "id": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
  "OrderDate": "2014-09-15T23:14:25.7251173Z",
  "ShipDate": "2014-09-30T23:14:25.7251173Z",
  "Total": 113.39
}

也可将 DateTime 存储为 Unix 时间戳,即存储为数字,用于表示自 1970 年 1 月 1 日以来已过去的秒数。 Azure Cosmos DB for NoSQL 的内部时间戳 (_ts) 属性遵循这种方法。 可以使用 UnixDateTimeConverter 类将日期和时间序列化为数字。

在 LINQ 中查询日期和时间

.NET SDK 自动支持使用语言集成查询 (LINQ) 查询存储的数据。 例如,以下代码片段显示一个 LINQ 查询,该查询筛选在过去三天内发运的订单:

IQueryable<Order> orders = container
    .GetItemLinqQueryable<Order>(allowSynchronousQueryExecution: true)
    .Where(o => o.ShipDate >= DateTime.UtcNow.AddDays(-3));

LINQ 查询将转换为以下 SQL 语句,并在 Azure Cosmos DB 上执行:

SELECT
    *
FROM
    root
WHERE
    (root["ShipDate"] >= "2014-09-30T23:14:25.7251173Z")

有关查询语言和 LINQ 提供程序的详细信息,请参阅 LINQ to SQL 翻译

为范围查询编制索引日期和时间

查询通常使用 DateTime 值。 若要高效执行这些查询,必须已在查询筛选器中的任何属性上定义索引。

有关如何配置索引策略的详细信息,请参阅 索引策略