sql >> データベース >  >> NoSQL >> MongoDB

Morphiaの紹介–MongoDB用のJavaODM

    1。概要

    このチュートリアルでは、JavaでMongoDB用のオブジェクトドキュメントマッパー(ODM)であるMorphiaを使用する方法を理解します。

    その過程で、ODMとは何か、そしてそれがMongoDBでの作業をどのように促進するかについても理解します。

    2。 ODMとは ?

    この分野の初心者にとって、 MongoDBは、本質的に配布されるように構築されたドキュメント指向のデータベースです 。ドキュメント指向データベースは、簡単に言えば、ドキュメントを管理します。ドキュメントは、半構造化データを整理するスキーマレスの方法に他なりません。 。これらは、SQLデータベースの従来の編成からの明らかな逸脱にちなんで名付けられた、広く大まかに定義されたNoSQLデータベースの傘下にあります。

    MongoDBは、Javaなどのほとんどすべての一般的なプログラミング言語用のドライバーを提供します 。これらのドライバーは、MongoDBを操作するための抽象化レイヤーを提供するため、WireProtocolを直接操作することはありません。これは、Oracleがリレーショナルデータベース用のJDBCドライバーの実装を提供していると考えてください。

    ただし、JDBCを直接使用していた日々を思い出すと、特にオブジェクト指向のパラダイムでは、JDBCがいかに厄介になるかを理解できます。幸い、Hibernateのようなオブジェクトリレーショナルマッピング(ORM)フレームワークがあります。 MongoDBでもそれほど違いはありません。

    確かに低レベルのドライバーで作業することはできますが、タスクを実行するにはさらに多くのボイラープレートが必要です。ここでは、オブジェクトドキュメントマッパー(ODM)と呼ばれるORMと同様の概念があります。 。 Morphiaは、Javaプログラミング言語のスペースを正確に埋め、MongoDBのJavaドライバーの上で動作します。

    3。依存関係の設定

    いくつかのコードに入るのに十分な理論を見てきました。この例では、本のライブラリをモデル化し、Morphiaを使用してMongoDBでそれを管理する方法を確認します。

    ただし、始める前に、いくつかの依存関係を設定する必要があります。

    3.1。 MongoDB

    動作させるには、MongoDBの実行中のインスタンスが必要です。これを取得するにはいくつかの方法がありますが、最も簡単な方法は、コミュニティエディションをローカルマシンにダウンロードしてインストールすることです。

    MongoDBが実行されるポートを含め、すべてのデフォルト構成をそのままにしておく必要があります。

    3.2。モルヒネ

    Morphia用にビルド済みのJARをMavenCentralからダウンロードして、Javaプロジェクトで使用できます。

    ただし、最も簡単な方法は、Mavenなどの依存関係管理ツールを使用することです。

    <dependency>
        <groupId>dev.morphia.morphia</groupId>
        <artifactId>core</artifactId>
        <version>1.5.3</version>
    </dependency>

    4。 Morphiaを使用して接続するにはどうすればよいですか?

    これで、MongoDBがインストールおよび実行され、JavaプロジェクトでMorphiaがセットアップされたので、Morphiaを使用してMongoDBに接続する準備が整いました。

    それをどのように達成できるか見てみましょう:

    Morphia morphia = new Morphia();
    morphia.mapPackage("com.baeldung.morphia");
    Datastore datastore = morphia.createDatastore(new MongoClient(), "library");
    datastore.ensureIndexes();

    それはほとんどそれです!これをもっとよく理解しましょう。マッピング操作を機能させるには、次の2つが必要です。

    1. マッパー:これは、JavaPOJOをMongoDBコレクションにマッピングする役割を果たします。 。上記のコードスニペットでは、 Morphia その責任があるクラスです。 POJOを検索するパッケージをどのように構成しているかに注意してください。
    2. 接続:これは、マッパーがさまざまな操作を実行できるMongoDBデータベースへの接続です。クラスデータストア MongoClientのインスタンスをパラメータとして受け取ります (Java MongoDBドライバーから)およびMongoDBデータベースの名前、使用するアクティブな接続を返す

    これで、このデータストアを使用する準備が整いました。 エンティティと連携します。

    5。エンティティを操作する方法は?

    作りたてのデータストアを使用する前に 、操作するドメインエンティティを定義する必要があります。

    5.1。単純なエンティティ

    簡単なを定義することから始めましょう いくつかの属性を持つエンティティ:

    @Entity("Books")
    public class Book {
        @Id
        private String isbn;
        private String title;
        private String author;
        @Property("price")
        private double cost;
        // constructors, getters, setters and hashCode, equals, toString implementations
    }

    ここで注意すべき興味深い点がいくつかあります:

    • アノテーション@エンティティに注意してください これにより、このPOJOがODMマッピングに適格になります モルヒネによる
    • Morphiaは、デフォルトで、エンティティをそのクラスの名前でMongoDBのコレクションにマップしますが、これを明示的にオーバーライドできます(エンティティ Book に対して行ったように) ここ)
    • Morphiaは、デフォルトで、エンティティ内の変数を変数の名前でMongoDBコレクション内のキーにマップしますが、これもオーバーライドできます(変数 cost > ここ)
    • 最後に、アノテーション@ Id によって、エンティティ内の変数に主キーとして機能するようにマークを付ける必要があります。 (ここで本にISBNを使用しているように)

    5.2。関係のあるエンティティ

    ただし、現実の世界では、エンティティは見た目ほど単純ではなく、相互に複雑な関係を持っています。たとえば、私たちの単純なエンティティ Book パブリッシャーを持つことができます 他のコンパニオンブックを参照できます。それらをどのようにモデル化しますか?

    MongoDBは、関係を構築するための2つのメカニズム—参照と埋め込みを提供します 。名前が示すように、参照すると、MongoDBは関連データを別のドキュメントとして同じまたは異なるコレクションに保存し、そのIDを使用して参照するだけです。

    逆に、埋め込みを使用すると、MongoDBは関係を保存するか、親ドキュメント自体に埋め込みます。

    それらの使い方を見てみましょう。 パブリッシャーを埋め込むことから始めましょう

    @Embedded
    private Publisher publisher;

    十分に単純です。それでは、先に進んで他の本への参照を追加しましょう:

    @Reference
    private List<Book> companionBooks;

    それだけです— Morphiaは、MongoDBでサポートされているように、モデルの関係に便利な注釈を提供します。ただし、参照と埋め込みのどちらを選択するかは、データモデルの複雑さ、冗長性、一貫性から判断する必要があります 他の考慮事項の中で。

    この演習は、リレーショナルデータベースの正規化に似ています。

    これで、 Bookでいくつかの操作を実行する準備が整いました。 データストアを使用する 。

    6。いくつかの基本的な操作

    Morphiaを使用していくつかの基本的な操作を操作する方法を見てみましょう。

    6.1。保存

    Book のインスタンスを作成する、最も単純な操作から始めましょう。 MongoDBデータベースのライブラリ

    Publisher publisher = new Publisher(new ObjectId(), "Awsome Publisher");
    
    Book book = new Book("9781565927186", "Learning Java", "Tom Kirkman", 3.95, publisher);
    Book companionBook = new Book("9789332575103", "Java Performance Companion", 
      "Tom Kirkman", 1.95, publisher);
    
    book.addCompanionBooks(companionBook);
    
    datastore.save(companionBook);
    datastore.save(book);

    これは、MorphiaがMongoDBデータベースにコレクションを作成し、存在しない場合はアップサート操作を実行するのに十分です。

    6.2。クエリ

    MongoDBで作成したばかりの本をクエリできるかどうかを見てみましょう:

    List<Book> books = datastore.createQuery(Book.class)
      .field("title")
      .contains("Learning Java")
      .find()
      .toList();
    
    assertEquals(1, books.size());
    
    assertEquals(book, books.get(0));

    Morphiaでのドキュメントのクエリは、 Datastoreを使用してクエリを作成することから始まります。 次に、関数型プログラミングを愛する人たちを喜ばせるために、宣言的にフィルターを追加します!

    Morphiaは、フィルターと演算子を使用した、はるかに複雑なクエリ構築をサポートしています。さらに、Morphiaでは、クエリ内の結果の制限、スキップ、および順序付けが可能です。

    さらに、Morphiaを使用すると、MongoDB用のJavaドライバーで記述された生のクエリを使用して、必要に応じてより詳細に制御できます。

    6.3。更新

    主キーが一致する場合、保存操作で更新を処理できますが、Morphiaはドキュメントを選択的に更新する方法を提供します。

    Query<Book> query = datastore.createQuery(Book.class)
      .field("title")
      .contains("Learning Java");
    
    UpdateOperations<Book> updates = datastore.createUpdateOperations(Book.class)
      .inc("price", 1);
    
    datastore.update(query, updates);
    
    List<Book> books = datastore.createQuery(Book.class)
      .field("title")
      .contains("Learning Java")
      .find()
      .toList();
    
    assertEquals(4.95, books.get(0).getCost());

    ここでは、クエリと更新操作を作成して、クエリによって返されるすべての書籍の価格を1つ上げます。

    6.4。削除

    最後に、作成されたものを削除する必要があります!繰り返しになりますが、Morphiaを使用すると、非常に直感的です:

    Query<Book> query = datastore.createQuery(Book.class)
      .field("title")
      .contains("Learning Java");
    
    datastore.delete(query);
    
    List<Book> books = datastore.createQuery(Book.class)
      .field("title")
      .contains("Learning Java")
      .find()
      .toList();
    
    assertEquals(0, books.size());

    以前とまったく同じようにクエリを作成し、データストアで削除操作を実行します。 。

    7。高度な使用法

    MongoDBには、集計、インデックス作成、その他多くの高度な操作があります 。 Morphiaを使用してすべてを実行することはできませんが、その一部を実行することは確かに可能です。他の人にとっては、悲しいことに、MongoDBのJavaドライバーにフォールバックする必要があります。

    Morphiaを介して実行できるこれらの高度な操作のいくつかに焦点を当てましょう。

    7.1。集約

    MongoDBの集約により、一連のドキュメントを操作して集約された出力を生成できるパイプライン内の一連の操作を定義できます。 。

    Morphiaには、このような集約パイプラインをサポートするAPIがあります。

    すべての本が著者によってグループ化されるような方法で図書館データを集約したいとします。

    Iterator<Author> iterator = datastore.createAggregation(Book.class)
      .group("author", grouping("books", push("title")))
      .out(Author.class);

    では、これはどのように機能しますか?同じ古いデータストアを使用して集約パイプラインを作成することから始めます。 。 Book など、集計操作を実行するエンティティを提供する必要があります。 ここ。

    次に、ドキュメントを「作成者」ごとにグループ化し、「本」というキーの下に「タイトル」を集約します。最後に、ここではODMを使用しています。したがって、集約されたデータを収集するエンティティを定義する必要があります。この場合は、作成者です。 。

    もちろん、作成者というエンティティを定義する必要があります 本と呼ばれる変数を使用:

    @Entity
    public class Author {
        @Id
        private String name;
        private List<String> books;
        // other necessary getters and setters
    }

    もちろん、これはMongoDBによって提供される非常に強力な構造の表面を引っかいただけであり、詳細についてはさらに詳しく調べることができます。

    7.2。投影

    MongoDBでのプロジェクションを使用すると、クエリでドキュメントからフェッチするフィールドのみを選択できます。 。ドキュメントの構造が複雑で重い場合、これは、必要なフィールドが少ない場合に非常に役立ちます。

    クエリでタイトルが付いた本だけを取得する必要があるとしましょう:

    List<Book> books = datastore.createQuery(Book.class)
      .field("title")
      .contains("Learning Java")
      .project("title", true)
      .find()
      .toList();
     
    assertEquals("Learning Java", books.get(0).getTitle());
    assertNull(books.get(0).getAuthor());

    ここでは、ご覧のとおり、結果のタイトルのみが返され、著者やその他のフィールドは返されません。ただし、MongoDBに保存する際に、投影された出力を使用する場合は注意が必要です。これにより、データが失われる可能性があります!

    7.3。インデックス作成

    インデックスは、データベースを使用したクエリの最適化において非常に重要な役割を果たします。リレーショナルデータベースだけでなく、多くの非リレーショナルデータベースも同様です。

    MongoDBは、デフォルトで主キーに作成された一意のインデックスを使用して、コレクションのレベルでインデックスを定義します 。さらに、MongoDBを使用すると、ドキュメント内の任意のフィールドまたはサブフィールドにインデックスを作成できます。作成するクエリに応じて、キーにインデックスを作成することを選択する必要があります。

    たとえば、この例では、 Bookのフィールド「title」にインデックスを作成したい場合があります。 よくクエリを実行することになります:

    @Indexes({
      @Index(
        fields = @Field("title"),
        options = @IndexOptions(name = "book_title")
      )
    })
    public class Book {
        // ...
        @Property
        private String title;
        // ...
    }

    もちろん、追加のインデックスオプションを渡して、作成されるインデックスのニュアンスを調整することもできます。フィールドには@プロパティの注釈を付ける必要があることに注意してください インデックスで使用されます。

    さらに、クラスレベルのインデックスとは別に、Morphiaにはフィールドレベルのインデックスを定義するためのアノテーションもあります。

    7.4。スキーマ検証

    更新または挿入操作の実行中にMongoDBが使用できるコレクションのデータ検証ルールを提供するオプションがあります 。 MorphiaはAPIを通じてこれをサポートしています。

    有効な価格なしで本を挿入したくないとしましょう。スキーマ検証を活用してこれを実現できます:

    @Validation("{ price : { $gt : 0 } }")
    public class Book {
        // ...
        @Property("price")
        private double cost;
        // ...
    }

    ここで使用できるMongoDBによって提供される豊富な検証セットがあります。

    8。代替のMongoDBODM

    利用可能なMongoDBODMforJavaはMorphiaだけではありません。私たちのアプリケーションで使用することを検討できる他のいくつかがあります。ここではモルヒネとの比較について議論することはできませんが、私たちの選択肢を知ることは常に役に立ちます:

    • Spring Data:MongoDBを操作するためのSpringベースのプログラミングモデルを提供します
    • MongoJack:JSONからMongoDBオブジェクトへの直接マッピングを提供します

    これはJava用のMongoDBODMの完全なリストではありませんが、いくつかの興味深い代替手段が利用可能です!


    1. MongoDBインデックスビルド–ユーザーが新しいビルドをトリガーできないようにする

    2. マングースにネストされた配列を入力します

    3. 毎日のグループ化内のMongoDB集約

    4. マングースの親によってスコープされた埋め込みドキュメントの一意性の検証