MongoDBを使用した簡単なタグ付けの実装
1. 概要
このチュートリアルでは、JavaとMongoDBを使用した簡単なタグ付けの実装を見ていきます。
概念に慣れていない人のために、a tag is a keyword used as a “label” to group documents into different categories.これにより、ユーザーは同様のコンテンツをすばやくナビゲートでき、大量のデータを処理する場合に特に役立ちます。
そうは言っても、この手法がブログで非常に一般的に使用されているのは当然のことです。 このシナリオでは、対象のトピックに応じて、各投稿に1つ以上のタグがあります。 ユーザーが読み終わったら、タグの1つをたどって、そのトピックに関連するより多くのコンテンツを表示できます。
このシナリオを実装する方法を見てみましょう。
2. 依存
データベースにクエリを実行するには、MongoDBドライバーの依存関係をpom.xmlに含める必要があります。
org.mongodb
mongo-java-driver
3.6.3
この依存関係の現在のバージョンはhereで見つけることができます。
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 tags;
// getters and setters
}
4. タグの更新
データベースを設定し、いくつかのサンプル投稿を挿入したので、それらを更新する方法を見てみましょう。
タイトルを使用してOur repository class will include two methods to handle the addition and removal of tagsを検索します。 また、クエリが要素を更新したかどうかを示すブール値を返します。
public boolean addTags(String title, List 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 tags) {
UpdateResult result = collection.updateOne(
new BasicDBObject(DBCollection.ID_FIELD_NAME, title),
Updates.pullAll(TAGS_FIELD, tags));
return result.getModifiedCount() == 1;
}
追加にはpushの代わりにaddEachToSetメソッドを使用したため、タグがすでに存在する場合は、再度追加することはありません。
また、addToSet演算子は、新しいタグをネストされた配列として追加するため、機能しないことにも注意してください。これは、必要なものではありません。
Another way we can perform our updates is through the Mongo shell.たとえば、投稿JUnit5 with Java.を更新しましょう。特に、タグJavaとJUnit5を追加し、タグSpringと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 –は、指定された配列のa field contains any valueが含まれるドキュメントを返します。
-
$nin –は、指定された配列のa field doesn’t contain any valueが含まれるドキュメントを返します。
-
$all –は、指定された配列のa field contains all the valuesが含まれるドキュメントを返します。
We’ll define three methods to query the posts in relation to a collection of tags passed as arguments。 少なくとも1つのタグ、すべてのタグに一致し、タグに一致しない投稿を返します。 また、Java8のStreamAPIを使用して、ドキュメントとモデル間の変換を処理するためのマッピングメソッドを作成します。
public List postsWithAtLeastOneTag(String... tags) {
FindIterable results = collection
.find(Filters.in(TAGS_FIELD, tags));
return StreamSupport.stream(results.spliterator(), false)
.map(TagRepository::documentToPost)
.collect(Collectors.toList());
}
public List postsWithAllTags(String... tags) {
FindIterable results = collection
.find(Filters.all(TAGS_FIELD, tags));
return StreamSupport.stream(results.spliterator(), false)
.map(TagRepository::documentToPost)
.collect(Collectors.toList());
}
public List postsWithoutTags(String... tags) {
FindIterable 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) document.get(TAGS_FIELD));
return post;
}
繰り返しますが、let’s also take a look at the shell equivalent queriesです。 それぞれMongoDBまたはStream APIでタグ付けされ、Java 8とJUnit 5の両方でタグ付けされ、GroovyまたはScala:
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の学習にさらに興味がある場合は、we encourage you to read this introductory article。
いつものように、例のすべてのコードは利用可能なover on the Github projectです。