Azure Cosmos DB for NoSQL で日付を扱う
適用対象: NoSQL
Azure Cosmos DB for NoSQL は、ネイティブの JSON データ モデルを通して、スキーマの柔軟性とリッチなインデックス機能を提供します。 データベース、コンテナー、ドキュメント、ストアド プロシージャを含むすべての Azure Cosmos DB リソースは、JSON ドキュメントとしてモデル化されて保存されます。 ポータブルであることが求められる JSON (および Azure Cosmos DB) では、少数の基本的な型 (String、Number、Boolean、Array、Object、Null) しかサポートされません。 しかし、JSON は柔軟性が高いため、開発者およびフレームワークは、これらのプリミティブ型を使用したり、オブジェクトまたは配列として構成したりすることにより、より複雑な型を表現できます。
基本の型の他に、多くのアプリケーションでは日付や時刻の情報を表す DateTime
型が必要です。 この記事では、開発者が、.NET SDK を使用して Azure Cosmos DB で日付の格納、取得、クエリを行う方法を説明します。
DateTimes の格納
Azure Cosmos DB は、string、number、boolean、null、array、object などの JSON 型をサポートしています。 これは直接 DateTime
型をサポートしていません。 現時点では、NoSQL 用 API では日付のローカライズはサポートされていません。 そのため、日付と時刻の情報を文字列として保存する必要があります。 日付と時刻の文字列に推奨される形式は yyyy-MM-ddTHH:mm:ss.fffffffZ
であり、これは ISO 8601 UTC 標準に準拠しています。 Azure Cosmos DB においてはすべての日付を UTC として保存することをお勧めします。 日付文字列をこの形式に変換すると、日付を辞書式で並べ替えることができます。 UTC 以外の日付が格納されている場合は、クライアント側でロジックを処理する必要があります。 ローカルの日付と時刻を UTC に変換するには、オフセットが JSON のプロパティとして認識/保存されている必要があります。クライアントはこのオフセットを使用して UTC の日付と時刻の値を計算できます。
日付と時刻文字列をフィルターとして使用する範囲クエリは、日付と時刻文字列がすべて UTC である場合にのみサポートされています。 GetCurrentDateTime システム関数は、yyyy-MM-ddTHH:mm:ss.fffffffZ
の形式で現在の UTC の日付と時刻の ISO 8601 文字列の値を返します。
ほとんどのアプリケーションは、次に示す理由から、DateTime
の既定の文字列表現を使用している可能性があります。
- 文字列は比較することができ、DateTime 値は文字列に変換されるとき、その相対的な順序が維持されます。
- この方法では、JSON 変換のためのカスタム コードまたは属性は必要ありません。
- JSON に格納されている日付を人間が判読できます。
- この方法では、高速クエリ パフォーマンスのためのインデックスを利用できます。
たとえば、次のスニペットは、.NET SDK を使用して 2 つの DateTime
プロパティ (ShipDate
と OrderDate
) を含む Order
オブジェクトをドキュメントとして保存します。
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
}
または、DateTimes を Unix タイムスタンプ (つまり 1970 年 1 月 1 日からの経過秒数を表す数値) として保存することもできます。 Azure Cosmos DB for NoSQL の内部タイムスタンプ (_ts
) プロパティは、この方法に従っています。 UnixDateTimeConverter
クラスを使用して、日付と時刻を数値としてシリアル化できます。
LINQ での日付と時刻のクエリ実行
.NET SDK は、統合言語クエリ (LINQ) を使用する保存されたデータのクエリ実行を自動的にサポートします。 たとえば、次のスニペットは、3 日以内に出荷された注文をフィルター処理する 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
値では一般的なものです。 これらのクエリを効率的に実行するには、クエリのフィルターのプロパティにインデックスが定義されている必要があります。
インデックス作成ポリシーの詳細については、「インデックス作成ポリシー」を参照してください。