MongoDB のクエリ - .NET SDK
項目一覧
Realm .NET SDK の MongoClientとクエリ APIを使用して、.NET アプリケーション コードから直接 MongoDB Atlas に保存されているデータをクエリできます。 Atlas App Servicesは、ログインしたユーザーまたは各ドキュメントの内容に基づいて結果を安全に取得するためのコレクションにデータ アクセスルールを提供します。
次のアクションにより、Realm .NET SDK を使用する .NET アプリケーションからリンクされた MongoDB Atlas クラスターへのアクセスが可能になります。
注意
このページで説明されている各操作では、クエリを使用して、操作が実行されるコレクション内の特定のドキュメントを照合します。 フィルターがコレクション内の複数のドキュメントに一致する場合、ソートパラメーターを指定しない限り、ドキュメントは不特定の順序で返されます。 つまり、 findOne()
、 updateOne()
、またはdeleteOne()
関数のいずれかに並べ替えを指定しないと、操作はクエリに一致する任意のドキュメントと一致する可能性があります。 ソートについて詳しくは、 cursor.sort() を参照してください。
ユースケース
MongoDB データソースをクエリする理由はさまざまあります。 Atlas Device Sync を介してクライアント内のデータを操作することは、必ずしも現実的ではないか、可能な限りありません。 次の場合には、MongoDB をクエリすることをお勧めします。
データセットが大きいか、クライアント デバイスにデータセット全体のロードに対する制約がある
Realm でモデル化されていないドキュメントを取得している
アプリは厳密なスキーマを持たないコレクションにアクセスする必要があります
非 Realm サービスは、アクセスしたいコレクションを生成します。
網羅的なものではありませんが、これらは MongoDB を直接クエリする一般的なユースケースです。
前提条件
.NET アプリケーションから MongoDB をクエリする前に、App Services App で MongoDB Data Access を設定する必要があります。 バックエンド アプリを設定して Realm SDK クエリ Atlas を使用できるようにする方法については、App Services ドキュメントの「 MongoDB データアクセスの設定 」を参照してください。
セットアップ
MongoDB Atlas クラスター内のデータを直接操作するには、まず Realm アプリ内の Atlas サービスの名前を渡してMongoClientオブジェクトをインスタンス化します。 次に、操作するコレクションごとにMongoClient.DatabaseとMongoClient.Collectionをインスタンス化します。 次のコードでは、デフォルトの「mongodb-atlas」Atlas サービス名を使用し、「inventary」データベースに「grants」コレクション用のMongoClient.Collection
を作成します。
mongoClient = user.GetMongoClient("mongodb-atlas"); dbPlantInventory = mongoClient.GetDatabase("inventory"); plantsCollection = dbPlantInventory.GetCollection<Plant>("plants");
サンプルデータ
このページの例では、植物店のチェーンで販売されるさまざまな植物を説明する次の MongoDB コレクションを使用します。
{ _id: ObjectId("5f87976b7b800b285345a8c4"), name: "venus flytrap", sunlight: "full", color: "white", type: "perennial", _partition: "Store 42" }, { _id: ObjectId("5f87976b7b800b285345a8c5"), name: "sweet basil", sunlight: "partial", color: "green", type: "annual", _partition: "Store 42" }, { _id: ObjectId("5f87976b7b800b285345a8c6"), name: "thai basil", sunlight: "partial", color: "green", type: "perennial", _partition: "Store 42" }, { _id: ObjectId("5f87976b7b800b285345a8c7"), name: "helianthus", sunlight: "full", color: "yellow", type: "annual", _partition: "Store 42" }, { _id: ObjectId("5f87976b7b800b285345a8c8"), name: "petunia", sunlight: "full", color: "purple", type: "annual", _partition: "Store 47" }
マッピングクラス
MongoDB でオブジェクトを操作する場合は、BSON オブジェクトに対応する .NET クラス(POCO)を作成する必要があります。 これにより、汎用のBsonDocument
オブジェクトではなく、オブジェクトを直接直列化および逆直列化できます。 このページのすべての例では、この目的で次のPlant
マッピング クラスを使用しています。
public partial class Plant : IRealmObject { [ ] public ObjectId Id { get; set; } = ObjectId.GenerateNewId(); [ ] public string? Name { get; set; } [ ] [ ] public string? Sunlight { get; set; } [ ] [ ] public string? Color { get; set; } [ ] [ ] public string? Type { get; set; } [ ] public string? Partition { get; set; } } public enum Sunlight { Full, Partial } public enum PlantColor { White, Green, Yellow, Purple } public enum PlantType { Perennial, Annual }
注意
カスタム コンストラクターを提供する場合は、引数なしのパブリック コンストラクターを宣言する必要があります。
マッピング クラスの使用の詳細については、「 マッピング クラス 」 を参照してください ( MongoDB .NETドライバーのドキュメント)。
ドキュメントの作成
MongoDB データストアにドキュメントを作成するには、マッピング クラスをインスタンス化し、新しいオブジェクトをInsertOneAsync()に渡します。 InsertManyAsync() を使用すると、複数のドキュメントを作成し、1 回の呼び出しで挿入することもできます。
単一ドキュメントのインサート
InsertOneAsync() を使用して単一のドキュメントを挿入できます。
次のスニペットは、「Venus Flytrap」プランナーを説明する単一のドキュメントを「grants」コレクションに挿入します。
var plant = new Plant { Name = "Venus Flytrap", Sunlight = Sunlight.Full.ToString(), Color = PlantColor.White.ToString(), Type = PlantType.Perennial.ToString(), Partition = "Store 42" }; var insertResult = await plantsCollection.InsertOneAsync(plant); var newId = insertResult.InsertedId;
複数のドキュメントの挿入
InsertManyAsync() を使用して、複数のドキュメントを同時に挿入できます。
次のスニペットは、オブジェクトをインスタンス化してList<Plant>
に追加し、そのリストをInsertManyAsync()
に渡すことで、4 つのPlant
オブジェクトを「grants」コレクションに挿入します。
var sweetBasil = new Plant { Name = "Sweet Basil", Sunlight = Sunlight.Partial.ToString(), Color = PlantColor.Green.ToString(), Type = PlantType.Annual.ToString(), Partition = "Store 42" }; var thaiBasil = new Plant { Name = "Thai Basil", Sunlight = Sunlight.Partial.ToString(), Color = PlantColor.Green.ToString(), Type = PlantType.Perennial.ToString(), Partition = "Store 42" }; var helianthus = new Plant { Name = "Helianthus", Sunlight = Sunlight.Full.ToString(), Color = PlantColor.Yellow.ToString(), Type = PlantType.Annual.ToString(), Partition = "Store 42" }; var petunia = new Plant { Name = "Petunia", Sunlight = Sunlight.Full.ToString(), Color = PlantColor.Purple.ToString(), Type = PlantType.Annual.ToString(), Partition = "Store 47" }; var listofPlants = new List<Plant> { sweetBasil, thaiBasil, helianthus, petunia }; var insertResult = await plantsCollection.InsertManyAsync(listofPlants); var newIds = insertResult.InsertedIds;
ドキュメントを読む
データストアからドキュメントを検索するには、検索するプロパティを定義するBsonDocument
フィルターを作成し、そのフィルターをFindOneAsync()またはFindAsync( ) のいずれかに渡します。 また、 CountAsync() を呼び出して、フィルターに一致するすべてのドキュメントの数を取得することもできます。
単一ドキュメントの検索
次の例は、「name」プロパティが「ペインア」である植物を検索する方法を示しています。
var petunia = await plantsCollection.FindOneAsync( new { name = "Petunia" }, null);
複数ドキュメントの検索
次の例は、「type」プロパティが「perennial」であるすべての植物を検索する方法を示しています。
var allPerennials = await plantsCollection.FindAsync( new { type = PlantType.Perennial.ToString() }, new { name = 1 });
重要
並べ替え順序を指定するFindAsync()
の 3 つ目のパラメーターを使用しています。 複数のドキュメントをクエリする場合は、一貫した結果を得るために、ソート順序を含める必要があります。
コレクション内のドキュメントをカウント
次の例では、 コレクション内のすべての植物の数を返します。
var allPlants = await plantsCollection.CountAsync();
Update Documents
MongoDB データストア内の既存のドキュメントを更新するには、検索するプロパティを定義するBsonDocument
フィルターを作成し、変更するプロパティを定義する 2 つ目のBsonDocument
を作成します。 1 つのドキュメントのみをアップデートする場合は、両方のオブジェクトをUpdateOneAsync()に渡します。 複数のドキュメントを一括更新する場合は、 UpdateManyAsync() を呼び出します。
単一ドキュメントの更新
次のコードは、「名前」プロパティが「ペイン」である植物を検索し、その「s照合」プロパティを「部分的」に変更します。
var updateResult = await plantsCollection.UpdateOneAsync( new { name = "Petunia" }, new BsonDocument("$set", new BsonDocument("sunlight", Sunlight.Partial.ToString())) );
複数のドキュメントの更新
次のコードは、「_ partition」の値が「store 47」であるすべてのプランを検索し、すべてを「rea 51」に変更します。
var filter = new { _partition = "Store 47" }; var updateDoc = new BsonDocument("$set", new BsonDocument("_partition", "Area 51")); var updateResult = await plantsCollection.UpdateManyAsync( filter, updateDoc);
ドキュメントをアップサートする
UpdateOneAsync()とUpdateManyAsync( ) の両方には、更新をアップサートであるかどうかを指定する任意のブール値 プロパティがあります(つまり、ドキュメントが存在しない場合は作成する必要があります)。 デフォルトでは、アップサートは実行されません。
次の例では、 name
プロパティが「Pothos」、 type
プロパティが「perennial」、 sunlight
プロパティが「Full」である植物を検索します。 これらの条件に一致する植物の場合、このメソッドは植物の_partition
値を "Store 42" に更新します。 コレクション内にその名前のプランテーションが存在しない場合、 メソッドはアップデートを含む、定義されたすべてのプロパティを持つ新しいプランを作成します。
var filter = new BsonDocument() .Add("name", "Pothos") .Add("type", PlantType.Perennial.ToString()) .Add("sunlight", Sunlight.Full.ToString()); var updateResult = await plantsCollection.UpdateOneAsync( filter, new BsonDocument("$set", new BsonDocument("_partition", "Store 42")), upsert: true); /* The upsert will create the following object: { "name": "pothos", "sunlight": "full", "type": "perennial", "_partition": "Store 42" } */
Delete Documents
ドキュメントを削除するプロセスは、ドキュメントの作成(または更新)とほぼ同じです。照合するプロパティを定義するBsonDocument
を作成し、 DeleteOneAsync()のいずれかを呼び出します。 またはDeleteManyAsync()
単一ドキュメントの削除
次の例では、"name" プロパティ値が "T本番" である最初に見つけたドキュメントを削除します。
var filter = new BsonDocument("name", "Thai Basil"); var deleteResult = await plantsCollection.DeleteOneAsync(filter);
複数のドキュメントの削除
次の例では、「type」プロパティ値が「annial」であるすべてのドキュメントを削除しています。
var filter = new BsonDocument("type", PlantType.Annual); var deleteResult = await plantsCollection.DeleteManyAsync(filter);
ドキュメントの集計
集計操作は、集計パイプラインと呼ばれる一連のデータ集計ステージを通じてコレクション内のすべてのドキュメントを実行します。 集計を使用すると、ドキュメントのフィルタリングと変換、関連するドキュメントのグループに関するサマリー データの収集、その他の複雑なデータ操作が可能になります。
集計操作は集計ステージの配列を入力として受け入れ、 タスク を返します パイプラインによって処理されたドキュメントのコレクションに解決されます。
注意
Compass は、集計パイプラインをビルドし、C# や他の言語にエクスポートするためのユーティリティを提供します。 詳細については、「集計パイプライン ビルダ」を参照してください。
コレクション内のドキュメントをグループ化する
.NET SDK は、 AggregateAsync()メソッドとその一般的なオーバーロードを使用したコレクションの集計をサポートしています。
次の例では、植物コレクション内のすべてのドキュメントをtype
値でグループ化し、各型の数を集計して、昇順に並べ替えます。
var groupStage = new BsonDocument("$group", new BsonDocument { { "_id", "$type" }, { "count", new BsonDocument("$sum", 1) } }); var sortStage = new BsonDocument("$sort", new BsonDocument("_id", 1)); var aggResult = await plantsCollection.AggregateAsync(groupStage, sortStage); foreach (var item in aggResult) { var id = item["_id"]; var count = item["count"]; Console.WriteLine($"Plant type: {id}; count: {count}"); }
上記の例では、ネストされた一連の BsonDocument を使用してパイプラインを構築していますが、これは書き込みとデバッグが複雑になる可能性があります。 すでに QueryAPI を知っている 場合は、string BsonDocument_ParseL にクエリを として渡すことができます。 使用して複数のドキュメントを挿入できます。次の例では、前の例と同じ集計を実行します。
var groupStep = BsonDocument.Parse(@" { $group: { _id: '$type', count: { $sum: 1 } } } "); var sortStep = BsonDocument.Parse("{$sort: { _id: 1}}"); aggResult = await plantsCollection.AggregateAsync(groupStep, sortStep); foreach (var item in aggResult) { var id = item["_id"]; var count = item["count"]; Console.WriteLine($"Id: {id}, Count: {count}"); }
フィルター ドキュメント
$matchステージを使用して、標準の MongoDBクエリ構文を使用してドキュメントをフィルタリングできます。
次の例は、集計を使用するときにドキュメントをフィルタリングする方法を示しています。 この集計パイプラインがPlant
オブジェクトのコレクションを返すことがわかっているため、 AggregateAsync()メソッドの汎用オーバーライドを使用します。
var matchStage = new BsonDocument("$match", new BsonDocument("type", new BsonDocument("$eq", PlantType.Perennial))); // Alternate approach using BsonDocument.Parse(...) matchStage = BsonDocument.Parse(@"{ $match: { type: { $eq: '" + PlantType.Perennial + @"' } }}"); var sortStage = BsonDocument.Parse("{$sort: { _id: 1}}"); var aggResult = await plantsCollection.AggregateAsync<Plant>(matchStage, sortStage); foreach (var plant in aggResult) { Console.WriteLine($"Plant Name: {plant.Name}, Color: {plant.Color}"); }
プロジェクト データ
$projectステージを使用して、ドキュメントから特定のフィールドを含めたり省略したり、集計演算子を使用して新しいフィールドを計算したりできます。 プロジェクションは、次の 2 つの方法で機能します。
値により 1 のフィールドが明示的に含められます。 これには、指定されていないすべてのフィールドを暗黙的に除外するという副作用があります。
値が 0 のフィールドを暗黙的に除外します。これには、指定されていないすべてのフィールドが暗黙的に含まれるという副作用があります。
これらの 2 つのプロジェクション方法は相互に排他的です。つまり、フィールドを明示的に含める場合は、フィールドを明示的に除外することはできません。また、その逆も同様です。
注意
_id
フィールドは特別なケースで、明示的に指定されない限り、すべてのクエリに常に含まれます。 このため、 0
値を持つ_id
フィールドを除外しながら、同時に_partition
などの他のフィールドを1
とともに含めることができます。 _id
フィールドを除外するという特別なケースのみ、1 つの$project
ステージで除外と包含の両方が許可されます。
次の例は、集計を使用する場合に プロジェクトを使用する方法を示しています。 この例では、次のようになります。
" ID " プロパティを除外し、
「パーティション」、「タイプ」、および「名前」プロパティを含み、
"storeNumber" という新しいプロパティを作成します。このプロパティは、空白の _ partition 値を分割し、2 番目の部分のみを返すことによって構築されます。
var projectStage = new BsonDocument("$project", new BsonDocument { { "_id", 0 }, { "_partition", 1 }, { "type", 1 }, { "name", 1 }, { "storeNumber", new BsonDocument("$arrayElemAt", new BsonArray { new BsonDocument("$split", new BsonArray { "$_partition", " " }), 1 }) } }); var sortStage = BsonDocument.Parse("{$sort: { storeNumber: 1}}"); var aggResult = await plantsCollection.AggregateAsync(projectStage, sortStage); foreach (var item in aggResult) { Console.WriteLine($"{item["name"]} is in store #{item["storeNumber"]}."); }
次に、 BsonDocument.Parse()
メソッドを使用してprojectStage
を構築する方法も示します。
projectStage = BsonDocument.Parse(@" { _id:0, _partition: 1, type: 1, name: 1, storeNumber: { $arrayElemAt: [ { $split:[ '$_partition', ' ' ] }, 1 ] } }");