1. Przegląd
W tym samouczku zagłębimy się w strukturę agregacji MongoDB przy użyciu sterownika MongoDB Java .
Najpierw przyjrzymy się, co oznacza agregacja koncepcyjnie, a następnie skonfigurujemy zestaw danych. Na koniec zobaczymy różne techniki agregacji w działaniu przy użyciu Kreatora agregatów .
2. Czym są agregacje?
Agregacje są używane w MongoDB do analizowania danych i uzyskiwania z nich istotnych informacji .
Są one zwykle wykonywane w różnych etapach, a etapy tworzą potok – tak, że dane wyjściowe z jednego etapu są przekazywane jako dane wejściowe do następnego etapu.
Najczęściej używane etapy można podsumować jako:
Stage | odpowiednik SQL | Opis |
---|---|---|
projekt | WYBIERZ | wybiera tylko wymagane pola, może być również używany do obliczania i dodawania pól pochodnych do kolekcji |
dopasuj | GDZIE | filtruje kolekcję zgodnie z określonymi kryteriami |
grupa | GRUPUJ WG | zbiera dane wejściowe zgodnie z określonymi kryteriami (np. liczba, suma), aby zwrócić dokument dla każdego odrębnego grupowania |
sortuj | ORDER BY | sortuje wyniki w porządku rosnącym lub malejącym w danym polu |
liczba | COUNT | zlicza dokumenty, które zawiera kolekcja |
limit | LIMIT | ogranicza wynik do określonej liczby dokumentów, zamiast zwracać całą kolekcję |
out | WYBIERZ DO NEW_TABLE | zapisuje wynik do nazwanej kolekcji; ten etap jest akceptowalny tylko jako ostatni w potoku |
Ekwiwalent SQL dla każdego etapu agregacji znajduje się powyżej, aby dać nam wyobrażenie o tym, co ta operacja oznacza w świecie SQL.
Niedługo przyjrzymy się przykładom kodu Java dla wszystkich tych etapów. Ale wcześniej potrzebujemy bazy danych.
3. Konfiguracja bazy danych
3.1. Zbiór danych
Pierwszym i najważniejszym wymogiem uczenia się czegokolwiek związanego z bazą danych jest sam zestaw danych!
Na potrzeby tego samouczka użyjemy publicznie dostępnego, spokojnego punktu końcowego interfejsu API, który zapewnia wyczerpujące informacje o wszystkich krajach świata. Ten interfejs API zapewnia nam wiele punktów danych dla kraju w wygodnym formacie JSON . Niektóre z pól, których będziemy używać w naszej analizie, to:
- nazwisko – nazwa kraju; na przykład Stany Zjednoczone Ameryki
- alpha3Code – skrócony kod do nazwy kraju; na przykład IND (dla Indii)
- region – region, do którego należy kraj; na przykład Europa
- obszar – obszar geograficzny kraju
- języki – języki urzędowe kraju w formacie tablicowym; na przykład angielski
- granice – tablica kodów alpha3Code sąsiednich krajów s
Zobaczmy teraz, jak przekonwertować te dane na kolekcję w bazie danych MongoDB .
3.2. Importowanie do MongoDB
Najpierw musimy trafić do punktu końcowego API, aby pobrać wszystkie kraje i zapisać odpowiedź lokalnie w pliku JSON . Następnym krokiem jest zaimportowanie go do MongoDB za pomocą mongoimport polecenie:
mongoimport.exe --db <db_name> --collection <collection_name> --file <path_to_file> --jsonArray
Pomyślny import powinien dać nam kolekcję zawierającą 250 dokumentów.
4. Próbki agregacji w Javie
Teraz, gdy mamy już omówione podstawy, przejdźmy do uzyskania pewnych istotnych informacji na podstawie danych, które mamy dla wszystkich krajów . W tym celu użyjemy kilku testów JUnit.
Ale zanim to zrobimy, musimy nawiązać połączenie z bazą danych:
@BeforeClass
public static void setUpDB() throws IOException {
mongoClient = MongoClients.create();
database = mongoClient.getDatabase(DATABASE);
collection = database.getCollection(COLLECTION);
}
We wszystkich poniższych przykładach będziemy używać agregatów klasa pomocnicza dostarczana przez sterownik MongoDB Java.
Dla lepszej czytelności naszych fragmentów możemy dodać statyczny import:
import static com.mongodb.client.model.Aggregates.*;
4.1. dopasuj i count
Na początek zacznijmy od czegoś prostego. Wcześniej zauważyliśmy, że zbiór danych zawiera informacje o językach.
Załóżmy teraz, że chcemy sprawdzić liczbę krajów na świecie, w których angielski jest językiem urzędowym :
@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"));
}
W naszym potoku agregacji używamy dwóch etapów:match i count .
Najpierw odfiltrowujemy kolekcję, aby dopasować tylko te dokumenty, które zawierają język angielski w ich językach pole. Te dokumenty można sobie wyobrazić jako tymczasowy lub pośredni zbiór, który staje się danymi wejściowymi do naszego następnego etapu, count. Liczy to liczbę dokumentów na poprzednim etapie.
Inną kwestią, na którą należy zwrócić uwagę w tym przykładzie, jest użycie metody najpierw . Ponieważ wiemy, że wynik ostatniego etapu, count , będzie pojedynczym rekordem, jest to gwarantowany sposób wyodrębnienia pojedynczego dokumentu wynikowego.
4.2. grupa (z sumą ) i sortuj
W tym przykładzie naszym celem jest znalezienie regionu geograficznego zawierającego maksymalną liczbę krajów :
@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"));
}
Jak widać, używamy grupy i sortuj aby osiągnąć nasz cel tutaj .
Najpierw zbieramy liczbę krajów w każdym regionie, gromadząc suma ich wystąpień w zmiennej tally. Daje nam to pośredni zbiór dokumentów, z których każdy zawiera dwa pola:region i listę krajów w nim zawartych. Następnie sortujemy go w kolejności malejącej i wyodrębniamy pierwszy dokument, aby dać nam region z maksymalną liczbą krajów.
4.3. sortuj, limit, i out
Teraz użyjmy sortowania , limit i out wyodrębnić siedem największych krajów pod względem obszaru i zapisać je w nowej kolekcji :
@Test
public void givenCountryCollection_whenAreaSortedDescending_thenSuccess() {
collection.aggregate(Arrays.asList(
sort(Sorts.descending("area")),
limit(7),
out("largest_seven"))).toCollection();
MongoCollection<Document> largestSeven = database.getCollection("largest_seven");
assertEquals(7, largestSeven.countDocuments());
Document usa = largestSeven.find(Filters.eq("alpha3Code", "USA")).first();
assertNotNull(usa);
}
Tutaj najpierw posortowaliśmy daną kolekcję w porządku malejącym według obszaru Następnie użyliśmy Agregates#limit metoda ograniczająca wynik tylko do siedmiu dokumentów. Na koniec użyliśmy out etap, aby zdeserializować te dane do nowej kolekcji o nazwie largest_seven . Ta kolekcja może być teraz używana w taki sam sposób, jak każda inna – na przykład do znalezienia jeśli zawiera USA.
4.4. projekt, grupa (z maks.), dopasowanie
W naszym ostatnim przykładzie spróbujmy czegoś trudniejszego. Powiedzmy, że musimy sprawdzić, ile granic każdy kraj dzieli z innymi i jaka jest maksymalna taka liczba .
Teraz w naszym zbiorze danych mamy obramowania pole, które jest tablicą zawierającą listę alpha3Code s dla wszystkich sąsiadujących krajów narodu, ale nie ma żadnego pola, które bezpośrednio podałoby nam liczbę. Musimy więc ustalić liczbę krajów graniczących za pomocą projektu :
@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"));
}
Następnie, jak widzieliśmy wcześniej, pogrupujemy przewidywaną kolekcję, aby znaleźć maks wartość borderingCountries . Należy tutaj podkreślić, że maks akumulator podaje nam maksymalną wartość w postaci liczby , a nie cały Dokument zawierające wartość maksymalną. Musimy wykonać dopasowanie aby odfiltrować żądany Dokument jeśli mają być wykonane jakiekolwiek dalsze operacje.