sql >> Databáze >  >> NoSQL >> MongoDB

Agregace MongoDB pomocí Javy

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.


  1. Jak získat zpět novou hodnotu po aktualizaci ve vloženém poli?

  2. Naklonujte sbírku v MongoDB

  3. osvědčený postup sdružování django + PyMongo?

  4. Poslouchat změny v Redis?