この記事はシリーズの一部です。•Elasticsearchを使用した単純なタグ付けの実装
•JPAを使用した単純なタグ付けの実装
•JPAを使用した高度なタグ付けの実装
•MongoDBを使用した単純なタグ付けの実装(現在の記事)
1。概要
このチュートリアルでは、JavaとMongoDBを使用した簡単なタグ付けの実装を見ていきます。
概念に慣れていない人のために、タグはドキュメントをさまざまなカテゴリにグループ化するための「ラベル」として使用されるキーワードです。 これにより、ユーザーは同様のコンテンツをすばやくナビゲートでき、大量のデータを処理する場合に特に便利です。
そうは言っても、この手法がブログで非常に一般的に使用されているのは当然のことです。このシナリオでは、各投稿には、対象となるトピックに応じて1つ以上のタグがあります。ユーザーが読み終えたら、タグの1つをたどって、そのトピックに関連するその他のコンテンツを表示できます。
このシナリオを実装する方法を見てみましょう。
2。依存関係
データベースをクエリするには、MongoDBドライバーの依存関係を pom.xmlに含める必要があります。 :
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.6.3</version>
</dependency>
この依存関係の現在のバージョンはここにあります。
3。データモデル
まず、投稿ドキュメントがどのように表示されるかを計画することから始めましょう。
簡単にするために、データモデルにはタイトルのみが含まれ、ドキュメントID、作成者、およびいくつかのタグとしても使用されます。
投稿にはおそらく複数のタグが含まれるため、タグを配列内に格納します:
{
"_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;
}
addEachToSetを使用しました プッシュの代わりにメソッド タグがすでに存在する場合は、再度追加しないように追加します。
addToSetにも注意してください 演算子は、新しいタグをネストされた配列として追加するため、どちらも機能しません。これは、必要なものではありません。
更新を実行するもう1つの方法は、Mongoシェルを使用することです。 たとえば、投稿JUnit5をJavaで更新してみましょう。 特に、タグ Javaを追加します。 およびJUnit5 タグを削除します春 およびREST :
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つのタグ、すべてのタグに一致し、どのタグにも一致しない投稿を返します。また、Java8のStreamAPIを使用して、ドキュメントとモデル間の変換を処理するためのマッピングメソッドを作成します。
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でタグ付けされた3つの異なる投稿コレクションを取得します またはストリーム 両方のJava8でタグ付けされたAPI およびJUnit5 Groovyでタグ付けされていません スカラも :
db.posts.find({
"tags" : { $in : ["MongoDB", "Stream API" ] }
});
db.posts.find({
"tags" : { $all : ["Java 8", "JUnit 5" ] }
});
db.posts.find({
"tags" : { $nin : ["Groovy", "Scala" ] }
});