コード中にSQLクエリを書くとなんか汚く見えるし、パラメータークエリを使ったりSQLクエリがちょっと間違っていると動かなかったりするからいろいろと面倒!と思ったことはないでしょうか?
私はあります。
今回はSQLクエリを書かずにLINQ
を使ってAzure Cosmos DB
からデータを取得する方法について書きます。
LINQでCosmos DBからデータを取得
今回はContainer.GetItemLinqQueryable<>()
を使ってLINQコードを記述していきます。
Cosmos DBでは複雑なクエリを発行は基本することができません。
(別のデータベースを跨いでデータを取得したり、)
下記にクエリ例を記載します。
SELECT * FROM c where c.code = 01110
上記のクエリを実行することでcode = '01110'
を持つレコードを全て取得するクエリになります。
これを.NETのコードに落とし込むと・・・
var query = $"SELECT * FROM c where c.code = 01110";
var userdata = container.GetItemQueryIterator<UserData>(query);
う~ん、コード中にクエリ文挟みたくない。ワンクッション挟みたくない。(好みの話
そんな悩みを解決してくれる記述が以下のコードになります。
var userdata = container.GetItemLinqQueryable<UserData>(allowSynchronousQueryExecution: true).Where(c => c.Code == 01110)
1行になってすっきりした。しかもわかりやすい。
これはContainer.GetItemLinqQueryableメソッド
というAzure Cosmos DBのコンテナーの下にLINQクエリを作成してくれるメソッドを使用してLINQ文を書くことができます。
また、LINQの書き方を工夫することによってGeometryの比較を行う空間関数も扱うことができます。
container.GetItemLinqQueryable<UserData>(true).Where(x=>x.Geometry.Within(polygon))
LINQでデータを取得した後は非同期ストリーム(async streams)でデータを取得する。
方法を下記に記述するがforeachに渡してデータを取得する形となる。
foreach (var value in container.GetItemLinqQueryable<UserData>(true).Where(x=>x.Geometry.Within(polygon)))
{
Console.WriteLine(value.Geometry);
}
過去に100万件のデータ(Geometry込み)からデータを抽出した際の速度ではSQLクエリ側が2ms秒ほど高速に動作をしていた。
また、下記の結果はAzure Cosmos DB .NET SDK v3を利用して図ったものである。
container.GetItemLinqQueryable<UserData>(allowSynchronousQueryExecution: true).Where(u => u.Category == category)
SQLクエリ | LINQ文 |
45ms | 47ms |
余談
2021年10月12日現在はAzure Cosmos DB .NET SDKはv2とv3を利用することができる。
基本的にこれから始める場合はv3を利用するとよいでしょう。
また、v2に関しては2024年8月31日に廃止されることが決まっています。