Cosmos DB (Azure と Fabric) では、ネイティブ JSON データ モデルを使用してスキーマの柔軟性と豊富なインデックス作成を実現します。 データベース、コンテナー、ドキュメント、ストアド プロシージャを含むすべての Cosmos DB リソースは、JSON ドキュメントとしてモデル化および格納されます。 移植性の要件として、JSON (および Cosmos DB) では、String、Number、Boolean、Array、Object、Null という少数の基本型のみがサポートされます。 ただし、JSON は柔軟性が高く、開発者やフレームワークは、これらのプリミティブを使用してオブジェクトまたは配列として作成することで、より複雑な型を表すことができます。
多くのアプリケーションでは、基本的な型に加えて、日付と時刻の情報を表すために DateTime 型が必要です。 この記事では、開発者が .NET SDK を使用して Cosmos DB に日付を格納、取得、クエリする方法について説明します。
DateTimes を格納する
Cosmos DB では、文字列、数値、ブール値、null、配列、オブジェクトなどの JSON 型がサポートされています。
DateTime型は直接サポートされていません。 現時点では、NoSQL 用 API は日付のローカライズをサポートしていません。 そのため、日付と時刻の情報を文字列として格納する必要があります。 日付と時刻の文字列に推奨される形式は、ISO 8601 UTC 標準に従ってyyyy-MM-ddTHH:mm:ss.fffffffZ。 Cosmos DB のすべての日付を UTC として格納します。 日付文字列をこの形式に変換すると、辞書形式で日付を並べ替えられます。 UTC 以外の日付が格納されている場合、ロジックはクライアント側で処理する必要があります。 ローカルの日付と時刻の値を UTC に変換するには、オフセットを JSON のプロパティとして既知または格納する必要があります。クライアントはオフセットを使用して UTC の日付と時刻の値を計算できます。
日付と時刻の文字列をフィルターとして使用する範囲クエリは、日付と時刻の文字列がすべて UTC である場合にのみサポートされます。
GetCurrentDateTime システム関数は、現在の UTC 日時 ISO 8601 文字列値をyyyy-MM-ddTHH:mm:ss.fffffffZ形式で返します。
ほとんどのアプリケーションでは、次の理由から、 DateTime の既定の文字列表現を使用できます。
- 文字列は比較でき、DateTime 値の相対順序は文字列に変換されるときに保持されます。
- この方法では、JSON 変換にカスタム コードや属性は必要ありません。
- JSON に格納されている日付は人間が判読できます。
- この方法では、インデックスを利用して高速なクエリ パフォーマンスを実現できます。
たとえば、次のスニペットは、.NET SDK を使用してドキュメントとしてShipDateとOrderDateという 2 つのDateTime プロパティを含む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
}
``
Alternatively, you can store DateTimes as Unix timestamps, that is, as a number representing the number of elapsed seconds since **January 1, 1970**. Cosmos DB's internal timestamp (`_ts`) property follows this approach. You can use the [`UnixDateTimeConverter`](/dotnet/api/microsoft.azure.documents.unixdatetimeconverter) class to serialize dates and times as numbers.
## Query date and time in LINQ
The .NET SDK automatically supports querying data stored using Language Integrated Query (LINQ). For example, the following snippet shows a LINQ query that filters orders that were shipped in the last three days:
```csharp
IQueryable<Order> orders = container
.GetItemLinqQueryable<Order>(allowSynchronousQueryExecution: true)
.Where(o => o.ShipDate >= DateTime.UtcNow.AddDays(-3));
LINQ クエリは、次の SQL ステートメントに変換され、Cosmos DB で実行されます。
SELECT
*
FROM
root
WHERE
(root["ShipDate"] >= "2014-09-30T23:14:25.7251173Z")
クエリ言語と LINQ プロバイダーの詳細については、「 LINQ to SQL 変換」を参照してください。
範囲クエリのインデックスの日付と時刻
クエリは、 DateTime 値と共通です。 これらのクエリを効率的に実行するには、クエリのフィルター内のプロパティに対してインデックスを定義する必要があります。
インデックス作成ポリシーを構成する方法の詳細については、「 インデックス作成ポリシー」を参照してください。