LINQ
項目一覧
Overview
このガイドでは、MongoDB .NET/C# ドライバーで LINQ を使用する方法を説明します。LINQ では、言語キーワードと演算子を使用して、厳密に型指定されたオブジェクト コレクションを対象にクエリを作成できます。.NET/C# ドライバーは、LINQ クエリを自動的に集計操作に変換します。
このガイドの例では、Atlas サンプル データセットで提供されている sample_restaurants
データベースの restaurants
コレクションを使用します。無料の MongoDB Atlas クラスターを作成し、サンプル データセットをロードする方法については、 クイック スタートを参照してください。
次の Restaurant
、 Address
、およびGradeEntry
クラスは、このコレクション内のドキュメントをモデル化します。
public class Restaurant { public ObjectId Id { get; set; } public string Name { get; set; } [ ] public string RestaurantId { get; set; } public string Cuisine { get; set; } public Address Address { get; set; } public string Borough { get; set; } public List<GradeEntry> Grades { get; set; } }
public class Address { public string Building { get; set; } [ ] public float[] Coordinates { get; set; } public string Street { get; set; } [ ] public string ZipCode { get; set; } }
public class GradeEntry { public DateTime Date { get; set; } public string Grade { get; set; } public float Score { get; set; } }
注意
restaurants
コレクションのドキュメントは、キャメル ケースの命名規則を使用します。このガイドの例では、ConventionPack
を使用してコレクション内のフィールドをパスカル ケースに逆シリアル化し、Restaurant
クラスのプロパティにマップします。
カスタム直列化について詳しくは、「カスタム直列化」を参照してください。
コレクションをクエリ可能にします
LINQ を使用してコレクションをクエリするには、まずコレクションにリンクする IQueryable オブジェクトを作成する必要があります。オブジェクトを作成するには、次のように AsQueryable()
メソッドを使用します。
var restaurantsCollection = restaurantsDatabase.GetCollection<Restaurant>("restaurants"); var queryableCollection = restaurantsCollection.AsQueryable();
AsQueryable()
メソッドは、IQueryable
拡張メソッドと MongoDB 固有のメソッドのセットを持つ IMongoQueryable インスタンスを返します。
クエリ可能なオブジェクトを取得したら、メソッド構文を使用してクエリを作成できます。一部のパイプライン ステージでは、SQL クエリ構文に似たクエリ理解構文もサポートされています。
LINQ を使用してクエリを作成する方法を確認するには、Method Syntax または Query Syntax タブを選択します。
var query = queryableCollection .Where(r => r.Name == "The Movable Feast") .Select(r => new { r.Name, r.Address });
var query = from r in queryableCollection where r.Name == "The Movable Feast" select new { r.Name, r.Address };
前の例の結果を次のように印刷できます。
foreach (var restaurant in query) { Console.WriteLine(restaurant.ToJson()); }
{ "name" : "The Movable Feast", "address" : { "building" : "284", "coord" : [-73.982923900000003, 40.6580753], "street" : "Prospect Park West", "zipcode" : "11215" } }
Tip
クエリ結果へのアクセス
ToList()
または ToCursor()
メソッドを使用してクエリの結果にアクセスすることもできます。
var results = query.ToList();
var results = query.ToCursor();
サポートされている集計ステージ
LINQ を使用して集計パイプラインを作成できます。 .NET/C# ドライバーは、各 LINQ ステートメントを対応する集計パイプライン ステージに自動的に変換します。 このセクションでは、どの 集計パイプライン ステージ がサポートされているかを学習できます。
集計パイプライン ステージの詳細については、サーバー マニュアルの「集計ステージ」ページを参照してください。
$project
$project
集計ステージでは、指定されたフィールドのみを含むドキュメントが返されます。
LINQ を使用して $project
ステージを生成する方法を確認するには、 Method Syntax または Query Syntax タブを選択します。
var query = queryableCollection .Select(r => new { r.Name, r.Address });
var query = from r in queryableCollection select new { r.Name, r.Address };
前の例の結果には、次のドキュメントが含まれています。
{ "name" : "The Movable Feast", "address" : { "building" : "284", "coord" : [-73.982923900000003, 40.6580753], "street" : "Prospect Park West", "zipcode" : "11215" } }
注意
_idフィールドの除外
LINQ プロジェクションに _id
フィールドを含めない場合、.NET/C# ドライバーはそれを結果から自動的に除外します。
$match
$match
集計ステージでは、指定された条件に一致するドキュメントが返されます。
LINQ を使用して $match
ステージを生成する方法を確認するには、 Method Syntax または Query Syntax タブを選択します。
var query = queryableCollection .Where(r => r.Name == "The Movable Feast");
var query = from r in queryableCollection where r.Name == "The Movable Feast" select r;
前の例の結果には、次のドキュメントが含まれています。
// Results Truncated { "_id" : ObjectId(...), "name" : "The Movable Feast", "restaurant_id" : "40361606", "cuisine" : "American", "address" : {...}, "borough" : "Brooklyn", "grades" : [...] }
$limit
$limit
集計ステージでは、クエリによって返されるドキュメントの数を制限します。次の例は、LINQ を使用して $limit
ステージを生成する方法を示しています。
var query = queryableCollection .Where(r => r.Cuisine == "Italian") .Select(r => new {r.Name, r.Cuisine}) .Take(5);
前の例の結果には、次のドキュメントが含まれています。
{ "name" : "Philadelhia Grille Express", "cuisine" : "Italian" } { "name" : "Isle Of Capri Resturant", "cuisine" : "Italian" } { "name" : "Marchis Restaurant", "cuisine" : "Italian" } { "name" : "Crystal Room", "cuisine" : "Italian" } { "name" : "Forlinis Restaurant", "cuisine" : "Italian" }
$skip
$skip
集計ステージでは、クエリによって返された指定された数のドキュメントをスキップし、残りの結果を返します。次の例は、LINQ を使用して $skip
ステージを生成する方法を示しています。
var query = queryableCollection .Where(r => r.Cuisine == "Italian") .Select(r => new {r.Name, r.Cuisine}) .Skip(2);
上記の例では、条件に一致する最初の 2 つのレストランをスキップし、残りを返します。結果には、次のドキュメントが含まれています。
// Results Truncated { "name" : "Marchis Restaurant", "cuisine" : "Italian" } { "name" : "Crystal Room", "cuisine" : "Italian" } { "name" : "Forlinis Restaurant", "cuisine" : "Italian" } ...
$unwind
$unwind
集計ステージでは、指定された配列フィールドを分解し、その配列内の各要素のドキュメントを返します。
LINQ を使用して $unwind
ステージを生成する方法を確認するには、Method Syntax または Query Syntax タブを選択します。
var query = queryableCollection .Where(r => r.Name == "The Movable Feast") .SelectMany(r => r.Grades);
var query = from r in queryableCollection where r.Name == "The Movable Feast" from grade in r.Grades select grade;
前述の例のクエリは、 Name
フィールドの値が「The Movable Feast」であるドキュメントを検索します。次に、このドキュメントの Grades
配列内の各要素に対して、クエリは新しいドキュメントを返します。結果には、次のドキュメントが含まれています。
{ "date" : ISODate("2014-11-19T00:00:00Z"), "grade" : "A", "score" : 11 } { "date" : ISODate("2013-11-14T00:00:00Z"), "grade" : "A", "score" : 2 } { "date" : ISODate("2012-12-05T00:00:00Z"), "grade" : "A", "score" : 13 } { "date" : ISODate("2012-05-17T00:00:00Z"), "grade" : "A", "score" : 11 }
$group
$group
集計ステージでは、指定した基準に従ってドキュメントをグループに分割します。
LINQ を使用して $group
ステージを生成する方法を確認するには、Method Syntax または Query Syntax タブを選択します。
var query = queryableCollection .GroupBy(r => r.Cuisine) .Select(g => new { Cuisine = g.Key, Count = g.Count() });
var query = from r in queryableCollection group r by r.Cuisine into g select new {Cuisine = g.Key, Count = g.Count()};
上記の例では、各ドキュメントを Cuisine
フィールドの値でグループ化し、各 Cuisine
値を持つドキュメントの数をカウントします。結果には、次のドキュメントが含まれています。
// Results Truncated { "cuisine" : "Caribbean", "count" : 657 } { "cuisine" : "Café/Coffee/Tea", "count" : 1214 } { "cuisine" : "Iranian", "count" : 2 } { "cuisine" : "Nuts/Confectionary", "count" : 6 } { "cuisine" : "Middle Eastern", "count" : 168 } ...
注意
結果の順序
上記のクエリは必ずしも同じ順序で結果を返すわけではありません。この例を実行すると、上記とは異なる順序で結果が返される場合があります。
$sort
$sort
集計ステージでは、指定した順序でクエリの結果が返されます。
LINQ を使用して $sort
ステージを生成する方法を確認するには、Method Syntax または Query Syntax タブを選択します。
var query = queryableCollection .OrderBy(r => r.Name) .ThenByDescending(r => r.RestaurantId);
var query = from r in queryableCollection orderby r.Name, r.RestaurantId descending select r;
上記の例では、Name
フィールドでアルファベット順に並べ替えられ、RestaurantId
フィールドで 2 次降順で並べ替えられたクエリ結果が返されます。以下は返された結果に含まれるドキュメントのサブセットです。
// Results Truncated ... { "_id" : ObjectId(...), "name" : "Aba Turkish Restaurant", "restaurant_id" : "41548686", "cuisine" : "Turkish", "address" : {...}, "borough" : "Manhattan", "grades" : [...] } { "_id" : ObjectId(...), "name" : "Abace Sushi", "restaurant_id" : "50006214", "cuisine" : "Japanese", "address" : { ... }, "borough" : "Manhattan", "grades" : [...] } { "_id" : ObjectId(...), "name" : "Abacky Potluck", "restaurant_id" : "50011222", "cuisine" : "Asian", "address" : { ... }, "borough" : "Manhattan", "grades" : [...] } { "_id" : ObjectId(...), "name" : "Abaleh", "restaurant_id" : "50009096", "cuisine" : "Mediterranean", "address" : { ... }, "borough" : "Manhattan", "grades" : [...] } ...
$lookup
$lookup
集計ステージでは、1 つのコレクションのドキュメントを同じデータベース内の別のコレクションのドキュメントに結合します。$lookup
ステージでは、各入力ドキュメントに新しい配列フィールドが追加されます。新しい配列フィールドには、結合済みコレクションと一致するドキュメントが含まれます。
注意
ルックアップを実行するには、AsQueryable
メソッドを使用して両方のコレクションをクエリ可能にする必要があります。
コレクションをクエリ可能にする方法については、「 コレクションをクエリ可能にする 」を参照してください。
sample_restaurants
データベース内のレストランのレビューを含む reviews
という 2 番目のコレクションについて考えてみましょう。$lookup
ステージを使用して、そのコレクションのドキュメントを、restaurants
コレクション内の同じ name
値を持つドキュメントに結合できます。
次の Review
クラスは、reviews
コレクション内のドキュメントをモデル化します。
public class Review { public ObjectId Id { get; set; } [ ] public string RestaurantName { get; set; } public string Reviewer { get; set; } [ ] public string ReviewText { get; set; } }
LINQ を使用して $lookup
ステージを生成する方法を確認するには、 Method Syntax または Query Syntax タブを選択します。
var query = queryableCollection .GroupJoin(reviewCollection, restaurant => restaurant.Name, review => review.RestaurantName, (restaurant, reviews) => new { Restaurant = restaurant, Reviews = reviews } );
var query = from restaurant in queryableCollection join rv in reviewCollection on restaurant.Name equals rv.RestaurantName into reviews select new { restaurant, reviews };
上記の例では、restaurants
コレクションからすべてのドキュメントが返されます。各レストランのドキュメントには、reviews
というフィールドが追加されており、そのレストランのすべてのレビューが含まれています。レビュー ドキュメントの name
フィールドの値がレストラン ドキュメントの name
フィールドと一致する場合、レビューはレストランと一致します。
以下は、返された結果のサブセットです。
// Results Truncated { "restaurant" : { "_id" : ObjectId("..."), "name" : "The Movable Feast", "restaurant_id" : "40361606", "cuisine" : "American", "address" : {...}, "borough" : "Brooklyn", "grades" : [...] }, "reviews" : [ { "_id" : ObjectId(...), "restaurant_name" : "The Movable Feast", "reviewer" : "Lazlo Cravensworth", "review_text" : "Great restaurant! 12/10 stars!" }, { "_id" : ObjectId("..."), "restaurant_name" : "The Movable Feast", "reviewer" : "Michael Scarn", "review_text" : "It really was a feast" } ] }
サポートされていない集計ステージ
MongoDB .NET/C# ドライバーの LINQ 実装では、次の集計ステージはサポートされていません。
$redact
$geoNear
$out
サポートされているメソッド
以下は、MongoDB .NET/C# ドライバーの LINQ 実装でサポートされているメソッドの一部です。
メソッド名 | 説明 |
---|---|
Any | 指定された条件に一致するドキュメントがあるかどうかを判定します |
Average | 指定されたフィールドの平均を計算します |
Count | 指定された条件に一致するドキュメントの数を表す Int32 を返します。 |
LongCount | 指定された条件に一致するドキュメントの数を表す Int64 を返します。 |
Distinct | 指定された条件に一致する個別のドキュメントを返します |
First | 最初に一致するドキュメントを返し、見つからない場合は例外をスローします。 |
FirstOrDefault | 最初に一致するドキュメントを返します。見つからない場合は null を返します。 |
GroupBy | 指定した条件に基づいてドキュメントをグループ化します |
GroupJoin | 同じデータベース内の別のコレクションへの左外部結合を実行します |
Max | 指定された最大値を持つドキュメントを返します |
OfType | 指定した型に一致するドキュメントを返します |
OrderBy , OrderByDescending | 指定されたソート順序で結果を返します |
ThenBy , ThenByDescending | 二次ソートを指定できるようにします |
Select | 指定された基準に基づいてドキュメントを選択します |
SelectMany | シーケンスの各要素を投影し、結果のシーケンスを 1 つのドキュメントに結合します。 |
Single | 一致するドキュメントのみを返し、ドキュメントが1つだけない場合は例外をスローします |
SingleOrDefault | 一致するドキュメントを 1 つ返すか、一致するドキュメントがない場合は null を返します。 |
Skip | 指定された数の文書をスキップし、残りの結果を返します |
Sum | 指定されたフィールドの値の合計を返します |
Take | 返される結果の数を指定します |
Where | 指定した条件に一致するすべてのドキュメントを返します |