Czy wiesz, że wynikiem zapytania w MongoDB możesz zasilić bezpośrednio inną kolekcję?
MongoDB w wersji 4.2 udostępnił nowy etap potoku agregacji (ang. aggregation pipeline) - $merge. Pozwala on na zapisanie wyniku agregacji do określonej kolekcji.
Etap $merge
:
- Może wyprowadzać dane do kolekcji w tej samej lub innej bazie danych,
- utworzyć nową kolekcję, jeśli kolekcja jeszcze nie istnieje,
- może merge’ować wyniki do istniejącej kolekcji.
{
$merge: {
into: <collection> -or- { db: <db>, coll: <collection> },
on: <identifier field> -or- [ <identifier field1>, ...],
let: <variables>,
whenMatched: <replace|keepExisting|merge|fail|pipeline>,
whenNotMatched: <insert|discard|fail>
}
}
Etap $merge
zawsze musi być ostatnim etapem agregacji. Możemy określić następujące parametry:
into
- kolekcja, do której chcemy zapisać wynik; może to być kolekcja w innej bazie np.:into: { db:"myDB", coll:"myOutput" }
,on
- pole lub pola, które działają jako unikalny identyfikator dokumentu. Identyfikator określa, czy dokument wynikowy pasuje do istniejącego dokumentu w kolekcji wyjściowej. Domyślnie_id
, jeśli wskażemy inne pola, to musi być na nich unikalny indeks,let
- zmienne wykorzystywane w whenMatched,whenMatched
- rodzaj zachowania, gdy w kolekcji wyjściowej znajduje się taki sam dokument (dopasowany poon
),whenNotMatched
- rodzaj zachowania, gdy w kolekcji wyjściowej nie znaleziono dokumentu o takim samym identyfikatorze.
Dzięki $merge
możemy tworzyć zmaterializowane widoki na żądanie (ang. On-Demand Materialized View). Ciekawy przykład wprost z dokumentacji MongoDB:
Mamy 2 kolekcje:
db.purchaseorders.insertMany([
{_id: 1, quarter: "2019Q1", region: "A", qty: 200, reportDate: new Date("2019-04-01")},
{_id: 2, quarter: "2019Q1", region: "B", qty: 300, reportDate: new Date("2019-04-01")},
{_id: 3, quarter: "2019Q1", region: "C", qty: 700, reportDate: new Date("2019-04-01")},
{_id: 4, quarter: "2019Q2", region: "B", qty: 300, reportDate: new Date("2019-07-01")},
{_id: 5, quarter: "2019Q2", region: "C", qty: 1000, reportDate: new Date("2019-07-01")},
{_id: 6, quarter: "2019Q2", region: "A", qty: 400, reportDate: new Date("2019-07-01")}
])
db.reportedsales.insertMany([
{_id: 1, quarter: "2019Q1", region: "A", qty: 400, reportDate: new Date("2019-04-02")},
{_id: 2, quarter: "2019Q1", region: "B", qty: 550, reportDate: new Date("2019-04-02")},
{_id: 3, quarter: "2019Q1", region: "C", qty: 1000, reportDate: new Date("2019-04-05")},
{_id: 4, quarter: "2019Q2", region: "B", qty: 500, reportDate: new Date("2019-07-02")}
])
Potrzebujemy jednak raportu, który przedstawi nam sumaryczną sprzedaż i kupno dla poszczególnych kwartałów. Dane te będą nam często potrzebne, więc dobrze będzie je zapisać. Wykorzystamy do tego operator $merge
.
db.purchaseorders.aggregate([
{$group: {_id: "$quarter", purchased: {$sum: "$qty"}}},
{$merge: {into: "quarterlyreport", on: "_id", whenMatched: "merge", whenNotMatched: "insert"}}
])
Grupujemy wartości po czym zapisujemy je w kolekcji quarterlyreport
. Po takiej operacji otrzymujemy kolekcję quarterlyreport
:
{"_id": "2019Q2", "purchased": 1700}
{"_id": "2019Q1", "purchased": 1200}
Następnie przeprowadzamy analogiczną operację dla sprzedaży:
db.reportedsales.aggregate([
{$group: {_id: "$quarter", sales: {$sum: "$qty"}}},
{$merge: {into: "quarterlyreport", on: "_id", whenMatched: "merge", whenNotMatched: "insert"}}
])
W wyniku otrzymujemy kolekcję, która służy nam za widok ze zagregowanymi danymi. Warto zauważyć, że w wynikowej kolekcji dokumenty zostały zmergowane, a nie zastąpione:
{"_id": "2019Q1", "sales": 1950, "purchased": 1200}
{"_id": "2019Q2", "sales": 500, "purchased": 1700}
Przydatne linki:
-
SENIOR FULLSTACK DEVELOPER (JAVA + ANGULAR) Poznań (hybrydowo) lub zdalnie UoP 14 900 - 20 590 PLN brutto
B2B 19 680 - 27 220 PLN netto -
REGULAR FULLSTACK DEVELOPER (JAVA + ANGULAR) Poznań (hybrydowo) lub zdalnie UoP 11 300 - 15 900 PLN brutto
B2B 14 950 - 21 000 PLN netto -
ZOBACZ WSZYSTKIE OGŁOSZENIA
newsletter
techniczny
Podobne wpisy
Czy wiesz, że w Angular 17 została wprowadzona alternatywa dla *ngFor?
-
SENIOR FULLSTACK DEVELOPER (JAVA + ANGULAR) Poznań (hybrydowo) lub zdalnie UoP 14 900 - 20 590 PLN brutto
B2B 19 680 - 27 220 PLN netto -
REGULAR FULLSTACK DEVELOPER (JAVA + ANGULAR) Poznań (hybrydowo) lub zdalnie UoP 11 300 - 15 900 PLN brutto
B2B 14 950 - 21 000 PLN netto -
ZOBACZ WSZYSTKIE OGŁOSZENIA