1. Přehled
V tomto tutoriálu se ponoříme do rámce agregace MongoDB pomocí ovladače MongoDB Java .
Nejprve se podíváme na to, co agregace znamená koncepčně, a poté nastavíme datovou sadu. Nakonec uvidíme různé techniky agregace v akci pomocí nástroje Aggregates builder .
2. Co jsou agregace?
Agregace se v MongoDB používají k analýze dat a odvození smysluplných informací z nich .
Ty se obvykle provádějí v různých fázích a fáze tvoří potrubí – takže výstup z jedné fáze je předán jako vstup do další fáze.
Nejčastěji používané fáze lze shrnout takto:
Stage | ekvivalent SQL | Popis |
---|---|---|
projekt | VYBRAT | vybere pouze požadovaná pole, lze jej také použít k výpočtu a přidání odvozených polí do kolekce |
shoda | KDE | filtruje kolekci podle zadaných kritérií |
skupina | GROUP BY | shromažďuje vstupy podle zadaných kritérií (např. počet, součet) a vrací dokument pro každé samostatné seskupení |
řadit | OBJEDNAT | třídí výsledky ve vzestupném nebo sestupném pořadí daného pole |
počet | POČET | počítá dokumenty, které kolekce obsahuje |
limit | LIMIT | omezí výsledek na zadaný počet dokumentů namísto vrácení celé kolekce |
mimo | VYBRAT DO NEW_TABLE | zapíše výsledek do pojmenované kolekce; tato fáze je přijatelná pouze jako poslední v potrubí |
Ekvivalent SQL pro každou fázi agregace je uveden výše, abychom získali představu o tom, co uvedená operace znamená ve světě SQL.
Brzy se podíváme na ukázky kódu Java pro všechny tyto fáze. Ale předtím potřebujeme databázi.
3. Nastavení databáze
3.1. Datová sada
Prvním a nejdůležitějším požadavkem pro naučení čehokoli, co souvisí s databází, je samotná datová sada!
Pro účely tohoto tutoriálu použijeme veřejně dostupný klidný koncový bod API, který poskytuje komplexní informace o všech zemích světa. Toto rozhraní API nám poskytuje mnoho datových bodů pro zemi ve vhodném formátu JSON . Některá z polí, která budeme používat v naší analýze, jsou:
- jméno – název země; například Spojené státy americké
- alpha3Code – zkrácený kód pro název země; například IND (pro Indii)
- region – region, do kterého země patří; například Evropa
- oblast – zeměpisná oblast země
- jazyky – úřední jazyky země ve formátu pole; například angličtina
- hranice – pole alpha3Code sousedních zemí s
Nyní se podíváme, jak tato data převést na kolekci v databázi MongoDB .
3.2. Import do MongoDB
Nejprve musíme stisknout koncový bod API, abychom získali všechny země a uložili odpověď lokálně do souboru JSON . Dalším krokem je import do MongoDB pomocí mongoimport příkaz:
mongoimport.exe --db <db_name> --collection <collection_name> --file <path_to_file> --jsonArray
Úspěšným importem bychom měli získat kolekci s 250 dokumenty.
4. Ukázky agregace v Javě
Nyní, když máme pokryty základy, pojďme se pustit do odvození smysluplných poznatků z údajů, které máme pro všechny země . K tomuto účelu použijeme několik testů JUnit.
Ale než to uděláme, musíme se připojit k databázi:
@BeforeClass
public static void setUpDB() throws IOException {
mongoClient = MongoClients.create();
database = mongoClient.getDatabase(DATABASE);
collection = database.getCollection(COLLECTION);
}
Ve všech následujících příkladech budeme používat agregáty pomocná třída poskytovaná ovladačem MongoDB Java.
Pro lepší čitelnost našich úryvků můžeme přidat statický import:
import static com.mongodb.client.model.Aggregates.*;
4.1. shoda a počet
Pro začátek začněme něčím jednoduchým. Již dříve jsme poznamenali, že datová sada obsahuje informace o jazycích.
Nyní řekněme, že chceme zkontrolovat počet zemí na světě, kde je angličtina oficiálním jazykem :
@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"));
}
V našem procesu agregace používáme dvě fáze:shoda a počet .
Nejprve kolekci odfiltrujeme, aby odpovídala pouze těm dokumentům, které obsahují angličtinu v jejich jazycích pole. Tyto dokumenty si lze představit jako dočasnou nebo přechodnou sbírku, která se stane vstupem pro naši další fázi, count. Toto počítá počet dokumentů v předchozí fázi.
Dalším bodem, který je třeba v této ukázce poznamenat, je použití metody first . Protože víme, že výstup poslední fáze počítá , bude jeden záznam, je to zaručený způsob, jak extrahovat jediný výsledný dokument.
4.2. skupina (s součtem ) a řadit
V tomto příkladu je naším cílem zjistit geografickou oblast obsahující maximální počet zemí :
@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 je zřejmé, používáme skupinu a řadit abychom zde dosáhli našeho cíle .
Nejprve shromáždíme počet zemí v každém regionu nashromážděním součtu jejich výskytů v proměnné sčítat. To nám dává přechodnou sbírku dokumentů, z nichž každá obsahuje dvě pole:region a seznam zemí v něm. Poté jej seřadíme v sestupném pořadí a vyjmeme první dokument, abychom dostali region s maximálním počtem zemí.
4.3. řadit, limit, a ven
Nyní použijeme řazení , limit a ven extrahovat sedm největších zemí plošně a zapsat je do nové kolekce :
@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);
}
Zde jsme nejprve seřadili danou kolekci v sestupném pořadí podle oblasti Poté jsme použili Aggregates#limit způsob, jak omezit výsledek pouze na sedm dokumentů. Nakonec jsme použili out fázi deserializovat tato data do nové kolekce nazvané největší_sedm . Tuto sbírku lze nyní používat stejným způsobem jako kteroukoli jinou – například k vyhledání pokud obsahuje USA.
4.4. projekt, skupina (s max.), shoda
V naší poslední ukázce zkusme něco složitějšího. Řekněme, že potřebujeme zjistit, kolik hranic každá země sdílí s ostatními a jaký je maximální takový počet .
Nyní v naší datové sadě máme hranice pole, což je pole obsahující alpha3Code s pro všechny sousední země národa,ale neexistuje žádné pole, které by nám přímo udávalo počet. Budeme tedy muset odvodit počet hraničních zemí 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"));
}
Poté, jak jsme viděli dříve, se seskupíme projektovanou sbírku, abyste našli max hodnotu borderingCountries . Jedna věc, kterou je zde třeba zdůraznit, je max akumulátor nám udává maximální hodnotu jako číslo , nikoli celý dokument obsahující maximální hodnotu. Musíme provést zápas pro odfiltrování požadovaného dokumentu pokud mají být provedeny další operace.