\section{Aggregációk}

\begin{frame}{Mi az aggregáció?}
  \begin{block}{Aggregált lekérdezések}
    Adatok összesítése és elemzése számítások segítségével
  \end{block}
  
  \begin{block}{Prisma aggregáció műveletek}
    \begin{itemize}
      \item \texttt{count} - Rekordok számlálása
      \item \texttt{avg} - Átlag számítás
      \item \texttt{sum} - Összegzés
      \item \texttt{min} - Minimum érték
      \item \texttt{max} - Maximum érték
      \item \texttt{groupBy} - Csoportosítás
    \end{itemize}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Példa séma}
  \begin{block}{schema.prisma - Product}
    \begin{lstlisting}[language=JavaScript]
model Product {
  id          Int      @id @default(autoincrement())
  name        String
  price       Float
  stock       Int
  categoryId  Int
  category    Category @relation(fields: [categoryId], 
                                 references: [id])
  createdAt   DateTime @default(now())
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Példa séma (folyt.)}
  \begin{block}{schema.prisma - Category}
    \begin{lstlisting}[language=JavaScript]
model Category {
  id       Int       @id @default(autoincrement())
  name     String
  products Product[]
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Count - Számlálás}
  \begin{block}{Összes rekord számolása}
    \begin{lstlisting}[language=JavaScript]
const prisma = require('./prisma');
async function countProducts() {
  const count = await prisma.product.count();
  console.log(`Összes termék: ${count}`);
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Count - Számlálás (szűréssel)}
  \begin{block}{Szűrt számlálás}
    \begin{lstlisting}[language=JavaScript]
async function countExpensiveProducts() {
  const count = await prisma.product.count({
    where: {
      price: {
        gt: 1000
      }
    }
  });
  console.log(`Drága termékek: ${count}`);
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Aggregate - Alapok}
  \begin{block}{Egyszerű aggregáció}
    \begin{lstlisting}[language=JavaScript]
async function getProductStats() {
  const stats = await prisma.product.aggregate({
    _count: true,
    _avg: {price: true},
    _sum: {stock: true},
    _min: {price: true},
    _max: {price: true}
  });
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Aggregate - Alapok (folyt.)}
  \begin{block}{Egyszerű aggregáció}
    \begin{lstlisting}[language=JavaScript]
  console.log(stats);
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Aggregate - Eredmény}
  \begin{block}{Visszatérési érték példa}
    \begin{lstlisting}[language=JavaScript]
{
  _count: 150,
  _avg: {
    price: 1250.50
  },
  _sum: {
    stock: 5420
  },
  _min: {
    price: 99.99
  },
  _max: {
    price: 9999.99
  }}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Aggregate - Szűréssel}
  \begin{block}{Where feltétellel}
    \begin{lstlisting}[language=JavaScript]
async function getCategoryStats(categoryId) {
  const stats = await prisma.product.aggregate({
    where: {
      categoryId: categoryId
    },
    _count: true,
    _avg: {
      price: true
    },
    _sum: {
      stock: true
    }
  });
  return stats;
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{GroupBy - Csoportosítás}
  \begin{block}{Kategóriánkénti csoportosítás}
    \begin{lstlisting}[language=JavaScript]
async function groupByCategory() {
  const result = await prisma.product.groupBy({
    by: ['categoryId'],
    _count: true,
    _avg: {
      price: true
    },
    _sum: {
      stock: true
    }
  });
  
  return result;
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{GroupBy - Eredmény}
  \begin{block}{Csoportosított adatok}
    \begin{lstlisting}[language=JavaScript]
[
  {
    categoryId: 1,
    _count: 45,
    _avg: { price: 599.99 },
    _sum: { stock: 1200 }
  },
  {
    categoryId: 2,
    _count: 67,
    _avg: { price: 1299.50 },
    _sum: { stock: 890 }
  }
]
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{GroupBy - Having feltétel}
  \begin{block}{Szűrés az aggregált eredményen}
    \begin{lstlisting}[language=JavaScript]
async function getCategoriesWithHighAvgPrice() {
  const result = await prisma.product.groupBy({
    by: ['categoryId'],
    _avg: {price: true},
    _count: true,
    having: {
      price: {
        _avg: {gt: 1000}
      }
    }
  });
  return result;
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{GroupBy - Rendezés}
  \begin{block}{OrderBy aggregált mezőn}
    \begin{lstlisting}[language=JavaScript]
async function getCategoriesOrderedByAvgPrice() {
  const result = await prisma.product.groupBy({
    by: ['categoryId'],
    _avg: {price: true},
    _count: true,
    orderBy: {
      _avg: {price: 'desc'}
        }
  });
  return result;
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Több mező szerinti csoportosítás}
  \begin{block}{Összetett GroupBy}
    \begin{lstlisting}[language=JavaScript]
// Bővített séma szükséges: inStock boolean mező
async function groupByCategoryAndStock() {
  const result = await prisma.product.groupBy({
    by: ['categoryId', 'inStock'],
    _count: true,
    _avg: {price: true},
    orderBy: {categoryId: 'asc'}
  });
  return result;
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Relációk és aggregáció}
  \begin{block}{Kapcsolt táblák aggregálása}
    \begin{lstlisting}[language=JavaScript]
async function getCategoriesWithProductCount() {
  const categories = await prisma.category.findMany({
    include: {
      _count: {
        select: {
          products: true
        }
      }
    }
  });
  // Eredmény: [{ id: 1, name: 'Electronics', 
  //              _count: { products: 45 } }, ...]
  return categories;
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Relációs szűrés aggregációval}
  \begin{block}{Több mint N termékkel rendelkező kategóriák}
    \begin{lstlisting}[language=JavaScript]
async function getCategoriesWithManyProducts() {
  const categories = await prisma.category.findMany({
    where: {
      products: {some: {}}
    },
    include: {
      _count: {
        select: {products: true}
      }
    }});
  // Csak azok a kategóriák, amikhez van termék
  return categories.filter(c => c._count.products > 10);
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Express API - Statisztika endpoint}
  \begin{block}{Aggregált adatok REST API-n keresztül}
    \begin{lstlisting}[language=JavaScript]
const express = require('express');
const prisma = require('./prisma');
const app = express();

app.get('/api/stats/products', async (req, res) => {
  const stats = await prisma.product.aggregate({
    _count: true,
    _avg: { price: true },
    _sum: { stock: true },
    _min: { price: true },
    _max: { price: true }
  });
  res.json(stats);
});
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Express API - Csoportosított adatok}
  \begin{block}{GroupBy endpoint}
    \begin{lstlisting}[language=JavaScript]
app.get('/api/stats/by-category', async (req, res) => {
  const stats = await prisma.product.groupBy({
    by: ['categoryId'],
    _count: true,
    _avg: { price: true },
    _sum: { stock: true },
    orderBy: {
      _avg: {
        price: 'desc'
      }
    }
  });
  res.json(stats);
});
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Egyedi aggregáció - Raw Query}
  \begin{block}{SQL használata komplex esetekben}
    \begin{lstlisting}[language=JavaScript]
async function customAggregation() {
  const result = await prisma.$queryRaw`
    SELECT "categoryId",
      COUNT(*) as count,
      AVG(price) as avgPrice,
      SUM(stock) as totalStock
    FROM "Product"
    WHERE price > 100
    GROUP BY "categoryId"
    HAVING AVG(price) > 500
    ORDER BY avgPrice DESC
  `;
  return result;
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}{Aggregáció - Best Practices}
  \begin{block}{Ajánlások}
    \begin{itemize}
      \item Használj \texttt{select} és \texttt{where} feltételeket a teljesítmény növelésére
      \item GroupBy esetén mindig gondold át az indexelést
      \item Nagy adathalmazoknál fontold meg a lapozást
      \item Komplex esetekben raw SQL lehet hatékonyabb
      \item Cacheld az aggregált eredményeket, ha ritkán változnak
      \item Használj \texttt{having} feltételt az aggregált adatok szűrésére
    \end{itemize}
  \end{block}
\end{frame}

\begin{frame}{Összefoglalás}
  \begin{block}{Prisma aggregációk}
    \begin{itemize}
      \item \textbf{count} - Egyszerű és szűrt számlálás
      \item \textbf{aggregate} - Átlag, összeg, min, max számítások
      \item \textbf{groupBy} - Csoportosítás és aggregálás
      \item \textbf{having} - Szűrés aggregált eredményen
      \item \textbf{orderBy} - Rendezés aggregált mezők szerint
      \item \textbf{\_count} - Kapcsolt rekordok számlálása
    \end{itemize}
  \end{block}
\end{frame}
