Cosmos DB (Azure および Fabric) クエリ プロバイダーは、効率的なデータ取得のために言語統合クエリ (LINQ) を NoSQL クエリに変換します。 この記事では、サポートされている LINQ 演算子と、LINQ クエリを Cosmos DB 構文にマップする方法について説明します。これにより、.NET 開発者はデータベース クエリを最適化できます。 LINQ コードから変換された NoSQL クエリを表示するには、生成されたIQueryable オブジェクトで ToString() メソッドを使用します。 次の説明は、 LINQ に関する基本的な知識を前提としています。 LINQ に加えて、Cosmos DB では Entity Framework Core もサポートされています。これは、NoSQL 用 API で動作します。
注
最新の .NET SDK (Microsoft.Azure.Cosmos) バージョンを使用することをお勧めします
クエリ プロバイダー型システムでは、JSON プリミティブ型 ( numeric、 Boolean、 string、 null) のみがサポートされます。
クエリ プロバイダーでは、次のスカラー式がサポートされています。
クエリ評価時のプリミティブ データ型の定数値を含む定数値。
オブジェクトまたは配列要素のプロパティを参照するプロパティ/配列インデックス式。 例えば次が挙げられます。
family.Id; family.children[0].familyName; family.children[0].grade;int n = 1; family.children[n].grade;数値とブール値の一般的な算術式を含む算術式。
2 * family.children[0].grade; x + y;文字列比較式。文字列値と定数文字列値の比較が含まれます。
mother.familyName.StringEquals("Wakefield");string s = "Rob"; string e = "in"; string c = "obi"; child.givenName.StartsWith(s); child.givenName.EndsWith(e); child.givenName.Contains(c);複合値型または匿名型のオブジェクト、またはそのようなオブジェクトの配列を返すオブジェクト/配列作成式。 これらの値は入れ子にすることができます。
new Parent { familyName = "Wakefield", givenName = "Robin" }; new { first = 1, second = 2 }; //an anonymous type with two fields new int[] { 3, child.grade, 5 };
LINQ の使用
GetItemLinqQueryableを使用して LINQ クエリを作成できます。 この例では、LINQ クエリの生成と、 FeedIteratorを使用した非同期実行を示します。
using FeedIterator<Book> setIterator = container.GetItemLinqQueryable<Book>()
.Where(b => b.Title == "War and Peace")
.ToFeedIterator<Book>());
//Asynchronous query execution
while (setIterator.HasMoreResults)
{
foreach(var item in await setIterator.ReadNextAsync()){
{
Console.WriteLine(item.cost);
}
}
サポートされている LINQ 演算子
NoSQL .NET SDK に含まれる LINQ プロバイダーは、次の演算子をサポートしています。
-
選択: プロジェクションは、オブジェクトの構築を含め、
SELECTに変換されます。 -
Where: フィルターは
WHEREに変換され、noSQL 演算子への&&、||、および!間の変換をサポートします -
SelectMany:
JOIN句への配列のアンワインドを許可します。 配列要素をフィルター処理するために式を連結または入れ子にするために使用します。 -
OrderBy と OrderByDescending:
ASCまたはDESCを使用してORDER BYに翻訳します。 - 集計の Count、Sum、Min、Max、Average の演算子と、非同期の同等の CountAsync、SumAsync、MinAsync、MaxAsync、AverageAsync。
- CompareTo: 範囲比較に変換します。 .NET では比較できないため、この演算子は文字列に対して一般的に使用されます。
-
スキップと取得: クエリからの結果を制限し、改ページ処理を行うために、
OFFSETとLIMITに変換します。 -
数学関数: .NET
Abs、Acos、Asin、Atan、Ceiling、Cos、Exp、Floor、Log、Log10、Pow、Round、Sign、Sin、Sqrt、Tan、および同等の組み込み数学関数へのTruncateの変換をサポートします。 -
文字列関数: .NET
Concat、Contains、Count、EndsWith、IndexOf、Replace、Reverse、StartsWith、SubString、ToLower、ToUpper、TrimEnd、および同等の組み込み文字列関数へのTrimStartの変換をサポートします。 -
配列関数: .NET
Concat、Contains、およびCountから同等の 組み込み配列関数への変換をサポートします。 -
地理空間拡張関数: スタブ メソッドの
Distance、IsValid、IsValidDetailed、およびWithinから同等の 組み込みの地理空間関数への変換をサポートします。 -
User-Defined 関数拡張関数: スタブ メソッド
CosmosLinq.InvokeUserDefinedFunctionから対応するユーザー定義関数への変換をサポートします。 -
その他:
Coalesce演算子と 条件付き演算子の変換をサポートします。 コンテキストに応じて、Containsを文字列CONTAINS、ARRAY_CONTAINS、またはINに変換できます。
例示
次の例は、標準の LINQ クエリ演算子の一部が Cosmos DB のクエリにどのように変換されるかを示しています。
Select 演算子
構文は input.Select(x => f(x))で、 f はスカラー式です。 この場合、 inputは IQueryable オブジェクトになります。
Select 演算子、例 1:
LINQ ラムダ式
input.Select(family => family.parents[0].familyName);NoSQL
SELECT VALUE f.parents[0].familyName FROM Families f
Select 演算子、例 2:
LINQ ラムダ式
input.Select(family => family.children[0].grade + c); // c is an int variableNoSQL
SELECT VALUE f.children[0].grade + c FROM Families f
Select 演算子、例 3:
LINQ ラムダ式
input.Select(family => new { name = family.children[0].familyName, grade = family.children[0].grade + 3 });NoSQL
SELECT VALUE { "name":f.children[0].familyName, "grade": f.children[0].grade + 3 } FROM Families f
SelectMany 演算子
構文は input.SelectMany(x => f(x))です。ここで、 f はコンテナー型を返すスカラー式です。
LINQ ラムダ式
input.SelectMany(family => family.children);NoSQL
SELECT VALUE child FROM child IN Families.children
Where 演算子
構文は input.Where(x => f(x))です。ここで、 f はスカラー式であり、ブール値を返します。
Where 演算子、例 1:
LINQ ラムダ式
input.Where(family=> family.parents[0].familyName == "Wakefield");NoSQL
SELECT * FROM Families f WHERE f.parents[0].familyName = "Wakefield"
Where 演算子、例 2:
LINQ ラムダ式
input.Where( family => family.parents[0].familyName == "Wakefield" && family.children[0].grade < 3);NoSQL
SELECT * FROM Families f WHERE f.parents[0].familyName = "Wakefield" AND f.children[0].grade < 3
複合 NoSQL クエリ
上記の演算子を作成して、より強力なクエリを作成できます。 Cosmos DB では入れ子になったコンテナーがサポートされているため、コンポジションを連結または入れ子にすることができます。
連結
構文は input(.|.SelectMany())(.Select()|.Where())* です。 連結クエリは、省略可能な SelectMany クエリで始まり、その後に複数の Select 演算子または Where 演算子を続けることができます。
連結、例 1:
LINQ ラムダ式
input.Select(family => family.parents[0]) .Where(parent => parent.familyName == "Wakefield");NoSQL
SELECT * FROM Families f WHERE f.parents[0].familyName = "Wakefield"
連結、例 2:
LINQ ラムダ式
input.Where(family => family.children[0].grade > 3) .Select(family => family.parents[0].familyName);NoSQL
SELECT VALUE f.parents[0].familyName FROM Families f WHERE f.children[0].grade > 3
連結、例 3:
LINQ ラムダ式
input.Select(family => new { grade=family.children[0].grade}). Where(anon=> anon.grade < 3);NoSQL
SELECT * FROM Families f WHERE ({grade: f.children[0].grade}.grade > 3)
連結、例 4:
LINQ ラムダ式
input.SelectMany(family => family.parents) .Where(parent => parents.familyName == "Wakefield");NoSQL
SELECT * FROM p IN Families.parents WHERE p.familyName = "Wakefield"
ネスティング
構文はinput.SelectMany(x=>x.Q())QがSelect、SelectMany、またはWhere演算子です。
入れ子になったクエリは、外側のコンテナーの各要素に内部クエリを適用します。 1 つの重要な機能は、内部クエリが自己結合のように外部コンテナー内の要素のフィールドを参照できることです。
入れ子、例 1:
LINQ ラムダ式
input.SelectMany(family=> family.parents.Select(p => p.familyName));NoSQL
SELECT VALUE p.familyName FROM Families f JOIN p IN f.parents
入れ子、例 2:
LINQ ラムダ式
input.SelectMany(family => family.children.Where(child => child.familyName == "Jeff"));NoSQL
SELECT * FROM Families f JOIN c IN f.children WHERE c.familyName = "Jeff"
入れ子の例 3:
LINQ ラムダ式
input.SelectMany(family => family.children.Where( child => child.familyName == family.parents[0].familyName));NoSQL
SELECT * FROM Families f JOIN c IN f.children WHERE c.familyName = f.parents[0].familyName