Agregasi MongoDB Menggunakan Java

1. Ikhtisar

Dalam tutorial ini, kita akan mempelajari kerangka Agregasi MongoDB menggunakan driver Java MongoDB .

Pertama-tama kita akan melihat apa arti agregasi secara konseptual, lalu menyiapkan kumpulan data. Terakhir, kita akan melihat berbagai teknik agregasi beraksi menggunakan pembuat Agregat .

2. Apakah Agregasi Itu?

Agregasi digunakan di MongoDB untuk menganalisis data dan memperoleh informasi yang berarti darinya .

Ini biasanya dilakukan dalam berbagai tahap, dan tahapan tersebut membentuk pipeline - sedemikian rupa sehingga keluaran dari satu tahap diteruskan sebagai masukan ke tahap berikutnya.

Tahapan yang paling umum digunakan dapat diringkas sebagai:

Tahap Setara SQL Deskripsi
proyek PILIH memilih hanya bidang yang diperlukan, juga dapat digunakan untuk menghitung dan menambahkan bidang turunan ke koleksi
pertandingan DIMANA memfilter koleksi sesuai kriteria yang ditentukan
kelompok GRUP OLEH mengumpulkan masukan bersama-sama sesuai kriteria yang ditentukan (misalnya hitungan, jumlah) untuk mengembalikan dokumen untuk setiap pengelompokan yang berbeda
menyortir DIPESAN OLEH mengurutkan hasil dalam urutan menaik atau menurun dari bidang tertentu
menghitung MENGHITUNG menghitung dokumen yang dikoleksi
membatasi MEMBATASI membatasi hasil ke sejumlah dokumen tertentu, alih-alih mengembalikan seluruh koleksi
di luar PILIH INTO NEW_TABLE menulis hasilnya ke koleksi bernama; tahap ini hanya dapat diterima sebagai tahap terakhir dalam pipa

Setara SQL untuk setiap tahap agregasi disertakan di atas untuk memberi kita gambaran tentang apa arti operasi tersebut di dunia SQL.

Kami akan segera melihat contoh kode Java untuk semua tahapan ini. Namun sebelumnya, kita membutuhkan database.

3. Pengaturan Basis Data

3.1. Himpunan data

Persyaratan pertama dan terpenting untuk mempelajari apapun yang berhubungan dengan database adalah dataset itu sendiri!

Untuk tujuan tutorial ini, kami akan menggunakan titik akhir API tenang yang tersedia untuk umum yang menyediakan informasi lengkap tentang semua negara di dunia. API ini memberi kami banyak poin data untuk suatu negara dalam format JSON yang nyaman . Beberapa bidang yang akan kami gunakan dalam analisis kami adalah:

  • nama - nama negara; misalnya, Amerika Serikat
  • alpha3Code - kode pendek untuk nama negara; misalnya, IND (untuk India)

  • wilayah - wilayah negara tersebut; Misalnya, Eropa
  • area - wilayah geografis negara
  • bahasa - bahasa resmi negara dalam format array; misalnya, bahasa Inggris
  • perbatasan - array negara-negara tetangga alpha3Code s

Sekarang mari kita lihat bagaimana mengubah data ini menjadi koleksi dalam database MongoDB .

3.2. Mengimpor ke MongoDB

Pertama, kita perlu mencapai titik akhir API untuk mendapatkan semua negara dan menyimpan respons secara lokal dalam file JSON . Langkah selanjutnya adalah mengimpornya ke MongoDB menggunakan perintah mongoimport :

mongoimport.exe --db  --collection  --file  --jsonArray

Impor yang berhasil seharusnya memberi kami koleksi dengan 250 dokumen.

4. Sampel Agregasi di Jawa

Sekarang setelah kita memiliki dasar yang tercakup, mari kita mulai mendapatkan beberapa wawasan yang berarti dari data yang kita miliki untuk semua negara . Kami akan menggunakan beberapa pengujian JUnit untuk tujuan ini.

Tetapi sebelum kita melakukannya, kita perlu membuat koneksi ke database:

@BeforeClass public static void setUpDB() throws IOException { mongoClient = MongoClients.create(); database = mongoClient.getDatabase(DATABASE); collection = database.getCollection(COLLECTION); } 

Dalam semua contoh berikut, kita akan menggunakan kelas helper Agregat yang disediakan oleh driver Java MongoDB.

Untuk pembacaan yang lebih baik dari cuplikan kami, kami dapat menambahkan impor statis:

import static com.mongodb.client.model.Aggregates.*;

4.1. mencocokkan dan menghitung

Untuk memulainya, mari kita mulai dengan sesuatu yang sederhana. Sebelumnya kami mencatat bahwa kumpulan data berisi informasi tentang bahasa.

Sekarang, katakanlah kita ingin memeriksa jumlah negara di dunia yang menggunakan bahasa Inggris sebagai bahasa resmi :

@Test public void givenCountryCollection_whenEnglishSpeakingCountriesCounted_thenNinetyOne() { Document englishSpeakingCountries = collection.aggregate(Arrays.asList( match(Filters.eq("languages.name", "English")), count())).first(); assertEquals(91, englishSpeakingCountries.get("count")); }

Here we are using two stages in our aggregation pipeline: match and count.

First, we filter out the collection to match only those documents that contain English in their languages field. These documents can be imagined as a temporary or intermediate collection that becomes the input for our next stage, count. This counts the number of documents in the previous stage.

Another point to note in this sample is the use of the method first. Since we know that the output of the last stage, count, is going to be a single record, this is a guaranteed way to extract out the lone resulting document.

4.2. group (with sum) and sort

In this example, our objective is to find out the geographical region containing the maximum number of countries:

@Test public void givenCountryCollection_whenCountedRegionWise_thenMaxInAfrica() { Document maxCountriedRegion = collection.aggregate(Arrays.asList( group("$region", Accumulators.sum("tally", 1)), sort(Sorts.descending("tally")))).first(); assertTrue(maxCountriedRegion.containsValue("Africa")); }

As is evident, we are using group and sort to achieve our objective here.

First, we gather the number of countries in each region by accumulating a sum of their occurrences in a variable tally. This gives us an intermediate collection of documents, each containing two fields: the region and the tally of countries in it. Then we sort it in the descending order and extract the first document to give us the region with maximum countries.

4.3. sort,limit, and out

Now let's use sort, limit and out to extract the seven largest countries area-wise and write them into a new collection:

@Test public void givenCountryCollection_whenAreaSortedDescending_thenSuccess() { collection.aggregate(Arrays.asList( sort(Sorts.descending("area")), limit(7), out("largest_seven"))).toCollection(); MongoCollection largestSeven = database.getCollection("largest_seven"); assertEquals(7, largestSeven.countDocuments()); Document usa = largestSeven.find(Filters.eq("alpha3Code", "USA")).first(); assertNotNull(usa); }

Here, we first sorted the given collection in the descending order of area. Then, we used the Aggregates#limit method to restrict the result to seven documents only. Finally, we used the out stage to deserialize this data into a new collection called largest_seven. This collection can now be used in the same way as any other – for example, to find if it contains USA.

4.4. project, group (with max), match

In our last sample, let's try something trickier. Say we need to find out how many borders each country shares with others, and what is the maximum such number.

Now in our dataset, we have a borders field, which is an array listing alpha3Codes for all bordering countries of the nation, but there isn't any field directly giving us the count. So we'll need to derive the number of borderingCountries using project:

@Test public void givenCountryCollection_whenNeighborsCalculated_thenMaxIsFifteenInChina() { Bson borderingCountriesCollection = project(Projections.fields(Projections.excludeId(), Projections.include("name"), Projections.computed("borderingCountries", Projections.computed("$size", "$borders")))); int maxValue = collection.aggregate(Arrays.asList(borderingCountriesCollection, group(null, Accumulators.max("max", "$borderingCountries")))) .first().getInteger("max"); assertEquals(15, maxValue); Document maxNeighboredCountry = collection.aggregate(Arrays.asList(borderingCountriesCollection, match(Filters.eq("borderingCountries", maxValue)))).first(); assertTrue(maxNeighboredCountry.containsValue("China")); }

After that, as we saw before, we'll group the projected collection to find the max value of borderingCountries. One thing to point out here is that the max accumulator gives us the maximum value as a number, not the entire Document containing the maximum value. We need to perform match to filter out the desired Document if any further operations are to be performed.

5. Conclusion

In this article, we saw what are MongoDB aggregations, and how to apply them in Java using an example dataset.

Kami menggunakan empat sampel untuk mengilustrasikan berbagai tahap agregasi untuk membentuk pemahaman dasar tentang konsep tersebut. Ada beberapa kemungkinan untuk analisis data yang ditawarkan kerangka ini yang dapat dieksplorasi lebih lanjut .

Untuk bacaan lebih lanjut, Spring Data MongoDB menyediakan cara alternatif untuk menangani proyeksi dan agregasi di Java.

Seperti biasa, kode sumber tersedia di GitHub.