%Schriftgröße, Layout, Papierformat, Art des Dokumentes
\documentclass[10pt,oneside,a4paper,headsepline,footsepline]{scrartcl}

%Einstellungen der Seitenränder
\usepackage[left=2cm,right=2cm,top=1.5cm,bottom=1.5cm,includeheadfoot]{geometry}

%neue Rechtschreibung
\usepackage[ngerman]{babel}

%Umlaute ermöglichen
\usepackage[utf8]{inputenc}

%Gesamtseitenzahl
\usepackage{lastpage}

% Kopf- und Fußzeile
% Funktioniert nicht \usepackage[automark]{scrpage2}%
\usepackage[automark]{scrlayer-scrpage}

%Quellcode-Listings
\usepackage{listings}

%Hyperlinks
\usepackage{hyperref}

% Single quotes
\usepackage{upquote,textcomp}

%Kopfzeile
\ihead{Datenbanken}
\chead{}
\ohead{https://kohnlehome.de/datenbanken/mongodb-aggregation-pipeline.pdf}
%\setheadsepline{0.5pt}

%Fußzeile
%\setfootsepline{0.5pt}
\ifoot{Franz Kohnle}
\cfoot{Seite \thepage\ von  \pageref{LastPage}}
\ofoot{\today}

\pagestyle{scrheadings}

\begin{document}

% Single Quotes
\newcommand\upquote[1]{\textquotesingle#1\textquotesingle}

% Überschrift 
\begin{center}
\LARGE % Schriftgröße
\bfseries % Fettdruck
\sffamily % Serifenlose Schrift
MongoDB: Aggregation Pipeline
\end{center}


\section{Grundlagen}
\begin{verbatim}
db.collection.aggregate( [ { <stage1> }, { <stage2> }, ... ] )
\end{verbatim}

\section{Stages}
\subsection*{\$match: Zeilen filtern (wie bei find())}
\begin{verbatim}
    $match: { feld1: wert1 }
\end{verbatim}

\subsection*{\$project: Spalten filtern oder hinzufügen (Projektion)}
\begin{verbatim}
    $project: {
        _id: 0,                                        // nicht anzeigen
        feld1: 1,                                      // anzeigen
        "feldNeu": { $divide: ["$feld3", "$feld4"] }   // berechnetes Feld
    } 
\end{verbatim}

\subsubsection*{Arithmetische Operatoren}
\begin{verbatim}
    $add, $subtract, $multiply, $divide, $mod (Modulo)
\end{verbatim}

\subsection*{\$sort: sortieren}
\begin{verbatim}
    $sort: {
        feld1: 1,    //  1 = ASC
        feld2: -1    // -1 = DESC
    }
\end{verbatim}

\subsection*{\$group: Auswertung eines Feldes über alle Dokumente ohne Gruppierung}
\begin{verbatim}
    $group: {
        _id: null,                  // keine Gruppierung
        minimum: {$min: "$feld"},
        maximum: {$max: "$feld"},
        summe: {$sum: "$feld"},
        durchschnitt: {$avg: "$feld"}
    }
\end{verbatim}

\subsection*{\$group: Gruppierung}
\begin{verbatim}
    $group: { 
        _id: "$feld1",                   // Gruppierung nach feld1
        durchschnitt: {$avg: "$feld2"}   // Durchschnittlicher Wert von feld2
        anzahl: {$count: {}}             // Anzahl der Dokumente in Gruppe
    } 
\end{verbatim}

\subsection*{\$count: zählen}
\begin{verbatim}
    $count: 'Text'                       // Ausgabe: Text: <Anzahl>
\end{verbatim}

\subsection*{\$limit: Anzahl begrenzen}
\begin{verbatim}
    $limit: 5                            // nur 5 Dokumente
\end{verbatim}

\section{Beispiel: Alter aus Geburtsdatum berechnen}
\begin{verbatim}
    $project: {
        geburtsdatum: 1,                    // geburtsdatum anzeigen  
        "alter": {                          // neues Feld "alter"
            $floor: {                       // abrunden
                $divide: [                  // teilen
                    { 
                        $subtract: [        // subtrahieren
                            new Date(),     // Anzahl der Millisekunden seit 1.1.1970
                            "$geburtsdatum"
                        ]
                    },
                    (365 * 24*60*60*1000)   // Anzahl der Millisekunden pro Jahr
                                            // Schaltjahre werden nicht beachtet!
                ]      
            }
        }
    }
\end{verbatim}

\end{document}
