MongoDBおよびC#。 新機能と明白でない課題

はじめに



7月上旬、C#の公式 MongoDB ドライバーの次のバージョン(1.5)がリリースされました。 革新の中で、型付きクエリのサポートに注目する価値があります。 Expressionと組み合わせてラムダ関数を使用できるようになりました。

この記事では、私が本当に気に入っている新しい構文の例を示します(そして、C#のExpressionが本当に好きです)。また、悲しいかな、Expressionが役に立たず、通常の行に戻らなければならないクエリの例を示します。 また、なぜそうなのか、MongoDBを使用するときにC#で問題ないかどうかについても説明します。



いいね



はい、今ではなく:



ObjectId articleId = new ObjectId("dgdfg343ddfg"); IMongoQuery query = Query.EQ("_id", articleId);
      
      





次のように書くことができます:



 ObjectId articleId = new ObjectId("dgdfg343ddfg"); IMongoQuery query = Query<Article>.EQ(item => item.Id, articleId);
      
      





もちろん、文書の概要を表すクラスArticleの存在下で。 QueryBuilder <T>の選択に関連するすべてのメソッドは、QueryBuilderのメソッドと完全に類似していることに注意してください。 確かに、クエリを結合するには、Query.AndまたはQuery.Orを使用する必要があります。 すべてのメソッドが同じQueryBuilderを返すため、これは理解できます。 実際、好きなように組み合わせることができます。

UpdateBuilderは、適切なメソッドを持つUpdateBuilder <T>も導入しました。

以前のように:



 Article article = new Article(); IMongoUpdate update = Update.PushWrapped("Articles", article);
      
      





どうすれば今できる:



 Article article = new Article(); IMongoUpdate update = Update<Article>.Push(item => item.Articles, article);
      
      





私の意見では、はるかに優れています(美しさとコントロールについて話す場合)。 一般に、式ツリーは非常に強力で美しいものです。 ここでは、氷山の一角にすぎませんが、私はそれらを多くの場所で使用しました。 多くの点で、これは人間の顔の反射です。

まあ。 ここではすべてがシンプルに思えます。 あまり美しくないものに移りましょう。



ああ悲しい



値による検索のような単純なクエリはバタンと鳴ります。 ちなみに、もう少し複雑です。 たとえば、配列内の要素を検索する場合:



 IMongoQuery query = Query<Article>.ElemMatch<Comment>(item => item.Comments, builder => builder.EQ(item => item.Id, comment.Id));
      
      





しかし、緊張はすでに感じられています。

石炭をひっくり返しましょう。 このコンテンツのドキュメントがあります:



 _id : "s3d4f5d6sf", array1 : [{ _id : "cv434lfgd45", array2 : [{ _id : "df4gd45g43f4", name : "Logic" }, { ... }] }, { ... }]
      
      





そして今、別の要素をarray2配列に追加するタスクがあります。 プログラム内:



1)メインドキュメントはDocモデルクラスによって記述されます

2)array1をList <Item1>に変換します。Item1はarray1の各要素のモデルクラスです

3)array2をList <Item2>に変換します。Item2はarray2の各要素のモデルクラスです



(私は意図的に文書を匿名化したため、データ構造について苦情はありませんでした)



問題を見つけることに問題はありません:



 IMongoQuery query = Query.And( Query<Doc>.EQ(item => item.Id, new ObjectId("s3d4f5d6sf")), Query<Doc>.ElemMatch<Item1>(item => item.Array2, builder => builder.EQ(item => item.Id, new ObjectId("df4gd45g43f4")));
      
      





しかし、更新の要求が発生しました(ドキュメントを選択し、データを追加し、データベースに書き込むオプションを意識的に検討していません。オプションがあまりにも最適ではないため。さらに、サンプルのカスケードではなくアトミック操作でデータを更新したいレコード)。 ネストされたarray2配列に到達する必要があります。 MongoDBの標準ツールを使用している場合、これを行うことができます。



 IMongoUpdate update = Update.PushWrapped<Item2>("array1.$.array2", new Item2());
      
      





マジックラインを回避する方法がわかりませんでした。「array1。$。Array2」という表現を長く見れば見るほど、疑わしい思いがしました。



ああ高い



遠くから始めましょう。



「静的」言語があります。 たとえば、C#。 その中で、要素の構造はコンパイル前に知られています(ほとんどの場合)。 そして、私たちが運営しているのはこれらの構造です。 より具体的には、このようなスキームのクラスを操作します。 さて、データ側には、オブジェクト(クラスのインスタンス)があります。



「動的」言語があります。 たとえば、Javascript。 それらにおいて、通常の実行は実行中のデータ構造の形成です。 一般的な場合、「空の」オブジェクトを操作し、メソッドとフィールドを追加/削除します。 そのような構造はまったく存在しません。 構築の出発点(プロトタイプ)のみがあります。



データの編成では、特定の類似性を引き出すこともできます。

リレーショナルデータベースには、ハードデータスキーマとそれらの間の依存関係があります。

ドキュメント指向では、ドキュメント、ネスト、およびリストのみがあります。



そして今、私は空想し、より粗雑な類推を与えます。

“ array1。$。Array2”の場合のExpressionでのクエリの問題は、C#でドキュメント(オブジェクト)を操作するための構造(クラス)を操作することです。 リクエストの「パワー」は、火に燃料を追加します。 選択リクエストで最初の条件のみを残す場合、必要に応じて(multiupdateでフラグを設定する)、array2配列のそれぞれに要素を追加できます。 実際、美しいクエリは(たとえ記述できたとしても)「array1。$。Array2」に変換されます。 深いレベルのネストを持つより広範なドキュメントの場合、状況は悪化するだけです。



そのようなタスクのためにExpression構文を考え出すことは不可能だと言っているのではなく、この構文がその理解性を失うように思えます。 つまり、構文部分とセマンティック部分(直感的で明確なビジネス)の間の関係が溶けます。 私は自分のプロジェクトに何が欲しいのかよくわかりません。

私にとって結論は非常に明白です。比較的単純な場合の美しい構文はクールでクールですが、より複雑な状況では、Expressionは作業を単純化せず、不確実性を増加させるだけであることがわかります。



おわりに



MongoDBの使用経験はあまりないので、説明したクエリの問題に対する解決策と、MongoDBのC#でのアーキテクチャとコードの構築に関する論理的議論/議論を記事に喜んで掲載します。



All Articles