Artikel ini adalah bagian dari seri:• Implementasi Pemberian Tag Sederhana dengan Elasticsearch
• Implementasi Pemberian Tag Sederhana dengan JPA
• Implementasi Penandaan Lanjutan dengan JPA
• Implementasi Pemberian Tag Sederhana dengan MongoDB (artikel saat ini)
1. Ikhtisar
Dalam tutorial ini, kita akan melihat implementasi penandaan sederhana menggunakan Java dan MongoDB.
Bagi mereka yang tidak terbiasa dengan konsep tersebut, tag adalah kata kunci yang digunakan sebagai “label” untuk mengelompokkan dokumen ke dalam kategori yang berbeda. Hal ini memungkinkan pengguna untuk menavigasi konten serupa dengan cepat dan ini sangat berguna saat menangani data dalam jumlah besar.
Karena itu, tidak mengherankan bahwa teknik ini sangat umum digunakan di blog. Dalam skenario ini, setiap posting memiliki satu atau lebih tag sesuai dengan topik yang dibahas. Ketika pengguna selesai membaca, dia dapat mengikuti salah satu tag untuk melihat lebih banyak konten yang terkait dengan topik tersebut.
Mari kita lihat bagaimana kita dapat menerapkan skenario ini.
2. Ketergantungan
Untuk mengkueri database, kita harus menyertakan ketergantungan driver MongoDB di pom.xml kita :
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.6.3</version>
</dependency>
Versi ketergantungan saat ini dapat ditemukan di sini.
3. Model Data
Pertama-tama, mari kita mulai dengan merencanakan seperti apa tampilan dokumen pos.
Untuk membuatnya tetap sederhana, model data kami hanya akan memiliki judul, yang juga akan kami gunakan sebagai id dokumen, penulis, dan beberapa tag.
Kami akan menyimpan tag di dalam array karena sebuah postingan mungkin memiliki lebih dari satu:
{
"_id" : "Java 8 and MongoDB",
"author" : "Donato Rimenti",
"tags" : ["Java", "MongoDB", "Java 8", "Stream API"]
}
Kami juga akan membuat kelas model Java yang sesuai:
public class Post {
private String title;
private String author;
private List<String> tags;
// getters and setters
}
4. Memperbarui Tag
Sekarang kita telah menyiapkan database dan menyisipkan beberapa contoh postingan, mari kita lihat bagaimana kita dapat memperbaruinya.
Kelas repositori kami akan menyertakan dua metode untuk menangani penambahan dan penghapusan tag dengan menggunakan judul untuk menemukannya. Kami juga akan mengembalikan boolean untuk menunjukkan apakah kueri memperbarui elemen atau tidak:
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;
}
Kami menggunakan addEachToSet metode alih-alih push untuk penambahan agar jika tag sudah ada kita tidak akan menambahkannya lagi.
Perhatikan juga bahwa addToSet operator juga tidak akan berfungsi karena akan menambahkan tag baru sebagai array bersarang yang bukan yang kita inginkan.
Cara lain kami dapat melakukan pembaruan adalah melalui shell Mongo. Misalnya, perbarui postingan JUnit5 dengan Java. Secara khusus, kami ingin menambahkan tag Java dan JUnit5 dan hapus tag Musim Semi dan Istirahat :
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. Kueri
Last but not least, mari kita lihat beberapa pertanyaan paling umum yang mungkin menarik bagi kita saat bekerja dengan tag. Untuk tujuan ini, kami akan memanfaatkan tiga operator larik secara khusus:
- $in – mengembalikan dokumen di mana bidang berisi nilai apa pun dari larik yang ditentukan
- $nin – mengembalikan dokumen yang bidang tidak berisi nilai apa pun dari larik yang ditentukan
- $all – mengembalikan dokumen di mana bidang berisi semua nilai dari larik yang ditentukan
Kami akan mendefinisikan tiga metode untuk mengkueri postingan terkait dengan kumpulan tag yang diteruskan sebagai argumen . Mereka akan mengembalikan posting yang cocok dengan setidaknya satu tag, semua tag dan tidak ada tag. Kami juga akan membuat metode pemetaan untuk menangani konversi antara dokumen dan model kami menggunakan Stream API Java 8:
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;
}
Sekali lagi, mari kita lihat juga kueri yang setara dengan shell . Kami akan mengambil tiga koleksi pos berbeda yang masing-masing diberi tag dengan MongoDB atau Aliran API, ditandai dengan keduanya Java 8 dan JUnit 5 dan tidak ditandai dengan Groovy atau Skala :
db.posts.find({
"tags" : { $in : ["MongoDB", "Stream API" ] }
});
db.posts.find({
"tags" : { $all : ["Java 8", "JUnit 5" ] }
});
db.posts.find({
"tags" : { $nin : ["Groovy", "Scala" ] }
});