MongoDBを使った簡単なタグ付けの実装

1概要

このチュートリアルでは、JavaとMongoDBを使った簡単なタグ付けの実装を見ていきます。

概念に慣れていない人にとっては、 タグは文書をさまざまなカテゴリにグループ化するための「ラベル」として使用されるキーワードです これにより、ユーザーは同様のコンテンツをすばやくナビゲートでき、大量のデータを扱う場合に特に役立ちます。

とはいえ、この手法がブログで非常に一般的に使用されているのは当然のことです。このシナリオでは、対象となるトピックに従って、各投稿に1つ以上のタグがあります。ユーザーが読み終わったら、タグのいずれかをたどってそのトピックに関連するコンテンツをさらに表示できます。

このシナリオをどのように実装できるかを見てみましょう。

2依存

データベースをクエリするには、 pom.xml にMongoDBドライバの依存関係を含める必要があります。

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.6.3</version>
</dependency>

この依存関係の現在のバージョンはhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.mongodb%22%20AND%20a%3A%22mongo-java-driver%にあります22[ここ]

3データ・モデル

まず最初に、投稿文書がどのように見えるべきかを計画することから始めましょう。

わかりやすくするために、データモデルにはタイトルのみを設定します。タイトルは、ドキュメントID、作成者、および一部のタグとしても使用します。

1つの投稿には複数のタグが含まれる可能性があるため、タグは配列内に格納します。

{
    "__id" : "Java 8 and MongoDB",
    "author" : "Donato Rimenti",
    "tags" :["Java", "MongoDB", "Java 8", "Stream API"]}

対応するJavaモデルクラスも作成します。

public class Post {
    private String title;
    private String author;
    private List<String> tags;

   //getters and setters
}

4タグを更新する

データベースを設定し、いくつかのサンプル投稿を挿入したので、それらを更新する方法を見てみましょう。

  • 私たちのリポジトリクラスはタグを見つけるためにタイトルを使うことによって** タグの追加と削除を扱うための2つのメソッドを含みます。また、クエリが要素を更新したかどうかを示すブール値も返します。

public boolean addTags(String title, List<String> tags) {
    UpdateResult result = collection.updateOne(
      new BasicDBObject(DBCollection.ID__FIELD__NAME, title),
      Updates.addEachToSet(TAGS__FIELD, tags));
    return result.getModifiedCount() == 1;
}

public boolean removeTags(String title, List<String> tags) {
    UpdateResult result = collection.updateOne(
      new BasicDBObject(DBCollection.ID__FIELD__NAME, title),
      Updates.pullAll(TAGS__FIELD, tags));
    return result.getModifiedCount() == 1;
}

追加には push の代わりに addEachToSet メソッドを使用したので、タグが既に存在する場合は、再度追加することはありません。

addToSet 演算子は、新しいタグを入れ子になった配列として追加するため、どちらも機能しないことにも注意してください。

  • 更新を実行するもう1つの方法は、Mongoシェルを使用することです** たとえば、ポスト__JUnit5をJavaで更新します。

db.posts.updateOne(
    { __id : "JUnit 5 with Java" },
    { $addToSet :
        { "tags" :
            { $each :["Java", "JUnit5"]}
        }
});

db.posts.updateOne(
    {__id : "JUnit 5 with Java" },
    { $pull :
        { "tags" : { $in :["Spring", "REST"]}
    }
});

5クエリ

大事なことを言い忘れましたが、タグを操作しながら、私たちが興味を持っているかもしれないいくつかの最も一般的なクエリを見てみましょう。このために、特に3つの配列演算子を利用します。

  • $ in - は、フィールドに任意の値が含まれるドキュメントを返します。

指定された配列 $ nin - フィールドに が含まれていないドキュメント

指定された配列の値 $ all - は、フィールドにすべてのフィールドが含まれる文書を返します

指定された配列の値**

  • 引数として渡されたタグのコレクションに関連して投稿をクエリするための3つのメソッドを定義します** 。少なくとも1つのタグ、すべてのタグに一致し、どのタグにも一致しない投稿を返します。また、Java 8のStream APIを使用して、ドキュメントとモデル間の変換を処理するためのマッピングメソッドも作成します。

public List<Post> postsWithAtLeastOneTag(String... tags) {
    FindIterable<Document> results = collection
      .find(Filters.in(TAGS__FIELD, tags));
    return StreamSupport.stream(results.spliterator(), false)
      .map(TagRepository::documentToPost)
      .collect(Collectors.toList());
}

public List<Post> postsWithAllTags(String... tags) {
    FindIterable<Document> results = collection
      .find(Filters.all(TAGS__FIELD, tags));
    return StreamSupport.stream(results.spliterator(), false)
      .map(TagRepository::documentToPost)
      .collect(Collectors.toList());
}

public List<Post> postsWithoutTags(String... tags) {
    FindIterable<Document> results = collection
      .find(Filters.nin(TAGS__FIELD, tags));
    return StreamSupport.stream(results.spliterator(), false)
      .map(TagRepository::documentToPost)
      .collect(Collectors.toList());
}

private static Post documentToPost(Document document) {
    Post post = new Post();
    post.setTitle(document.getString(DBCollection.ID__FIELD__NAME));
    post.setAuthor(document.getString("author"));
    post.setTags((List<String>) document.get(TAGS__FIELD));
    return post;
}

繰り返しになりますが、シェルの同等のクエリも見てみましょう。 MongoDB または Stream API、それぞれ Java 8 および JUnit 5 のタグが付けられ、 Groovy Scala のタグも付けられていない3つの異なる投稿コレクションを取得します。

db.posts.find({
    "tags" : { $in :["MongoDB", "Stream API"]}
});

db.posts.find({
    "tags" : { $all :["Java 8", "JUnit 5"]}
});

db.posts.find({
    "tags" : { $nin :["Groovy", "Scala"]}
});

6. 結論

この記事では、タグ付けメカニズムを構築する方法を示しました。もちろん、ブログとは別に、この同じ方法論を他の目的に使用して再適用することもできます。

MongoDBの学習にさらに興味がある場合は、/java-mongodb[この紹介記事を読むことをお勧めします]をリンクします。

いつものように、例の中のすべてのコードはhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/java-mongodb[Githubプロジェクトの上で]利用可能です。