MongoDB¶
A labor során a MongoDB NoSQL adatbáziskezelő rendszer és a Mongo C# driver használatát gyakoroljuk komplexebb feladatokon keresztül.
Előfeltételek, felkészülés¶
A labor elvégzéséhez szükséges eszközök:
- Windows, Linux, vagy MacOS: Minden szükséges program platform független, vagy van platformfüggetlen alternatívája.
-
MongoDB Community Server (letöltés)
-
Telepítés nélkül Docker segítségével az alábbi paranccsal futtathatod a szervert
docker run --name swlab1-mongo -p 27017:27017 -d mongo
-
-
VSCode
- MongoDB for VSCode kiegészítő
- Minta adatbázis kódja (mongo.js)
- GitHub account és egy git kliens
- Microsoft Visual Studio 2022 az itt található beállításokkal
- Linux és MacOS esetén Visual Studio Code és a .NET SDK-val települő dotnet CLI használható.
-
.NET 8.0
A feladat megoldásához 8.0-es .NET SDK telepítése szükséges.
Windows-on Visual Studio verzió függvényében lehet, hogy telepítve van (lásd itt az ellenőrzés módját); ha nem, akkor a fenti linkről kell telepíteni (az SDK-t és nem a runtime-ot.) Linux és MacOS esetén telepíteni szükséges.
A labor elvégzéséhez használható segédanyagok és felkészülési anyagok:
- MongoDB adatbáziskezelő rendszer és a C# driver használata
- Lásd az Adatvezérelt rendszerek c. tárgy jegyzetei és gyakorlati anyagai között
- Hivatalos Microsoft tutorial Mongo-t használó Web API készítéséhez
- A labor során nem WebAPI-t készítünk, de a Mongo használat azonos formában történik.
Előkészület¶
A feladatok megoldása során ne felejtsd el követni a feladat beadás folyamatát.
Git repository létrehozása és letöltése¶
-
Moodle-ben keresd meg a laborhoz tartozó meghívó URL-jét és annak segítségével hozd létre a saját repository-dat.
-
Várd meg, míg elkészül a repository, majd checkout-old ki.
Jelszó a laborokban
Egyetemi laborokban, ha a checkout során nem kér a rendszer felhasználónevet és jelszót, és nem sikerül a checkout, akkor valószínűleg a gépen korábban megjegyzett felhasználónévvel próbálkozott a rendszer. Először töröld ki a mentett belépési adatokat (lásd itt), és próbáld újra.
-
Hozz létre egy új ágat
megoldas
néven, és ezen az ágon dolgozz. -
A
neptun.txt
fájlba írd bele a Neptun kódodat. A fájlban semmi más ne szerepeljen, csak egyetlen sorban a Neptun kód 6 karaktere.
Adatbázis létrehozása¶
Kövesd a gyakorlatanyagban leírt utasításokat az adatbáziskezelő rendszer elindításához és az adatbázis létrehozásához.
1. Feladat: Termékek lekérdezése és módosítása (7 pont)¶
Ebben a feladatban a Product
entitáshoz tartozó CRUD (létrehozás, listázás/olvasás, módosítás és törlés) utasításokat fogjuk megvalósítani.
Visual Studio solution megnyitása¶
Nyisd meg a letöltött repository-ban a Visual Studio solution-t (.sln
fájl). Ha a megnyitás során a Visual Studio azt jelezné, hogy a projekt típus nem támogatott, akkor telepítsd a Visual Studio hiányzó komponenseit (lásd itt).
NE frissíts semmilyen verziót
Ne frissítsd se a projektet, se a .NET verziót, se a NuGet csomagokat! Ha ilyen kérdéssel találkozol a solution megnyitása során, akkor mindig mondj nemet!
Munkád során a Dal.Repository
osztályba dolgozz! Ezen fájl tartalmát tetszőlegesen módosíthatod (feltéve, hogy továbbra is megvalósítja a Dal.IRepository
interfészt, továbbra is van egy konstruktora egyetlen IMongoDatabase
paraméterrel és természetesen továbbra is fordul a kód).
Az adatbázis elérése a Dal.MongoConnectionConfig
osztályban van. Ha szükséges, az adatbázis nevét megváltoztathatod a forrásban jelölt helyen.
A projekt minden egyéb tartalma már elő van készítve a munkához, a fentieken kívül máshol NE módosítsd!
Razor Pages
A webalkalmazás egy un. Razor Pages típusú ASP.NET Core projekt. Ez egy szerver oldalon renderelt megjelenítési réteg, ahol tehát a weboldal html kódját C# kód és a Razor template állítja elő. (A megjelenítési réteggel nem lesz feladatod, az már elő van készítve számodra.)
Webalkalmazás elindítása¶
Próbáld ki, hogy elindul-e a program.
-
Fordítsd le és indítsd el Visual Studio-ból az alkalmazást.
-
Nyisd meg böngészőben a http://localhost:5000/ oldalt.
Ha minden rendben ment, akkor bejött egy oldal, ahol az egyes feladatokat ki fogod tudni próbálni. (Az egyes feladatokra mutató linkek mögötti oldalak még nem működnek. Előbb még meg kell valósítani az adatelérési réteget.)
Neptun kód megjelenítése a weboldalon¶
A forráskód melletti képernyőképeken szerepelnie kell a Neptun kódodnak.
-
Nyisd meg a
Pages\Shared\_Layout.cshtml
fájlt. A fájl közepe felé keresd meg az alábbi részt, és írd át benne a Neptun kódodat.<div class="container body-content"> @RenderBody() <hr /> <footer> <p>@ViewData["Title"] - NEPTUN</p> </footer> </div>
-
Fordítsd le és indítsd el az alkalmazást ismét, nézd meg a kezdőoldalt. Az alján kell lásd a saját Neptun kódod.
FONTOS
A Neptun kódnak a fentiek szerint szerepelnie kell minden képernyőképen!
Listázás/olvasás¶
-
Első lépésként szükség lesz az adatbázisban található
products
kollekció elérésére a kódból. Ehhez vegyél fel egy új mezőt aRepository
osztályban, és inicializáld ezt a konstruktorban. Az ehhez szükségesIMongoDatabase
objektumot Dependency Injection segítségével, konstruktorparaméterként kaphatod meg.private readonly IMongoCollection<Entities.Product> _productCollection; public Repository(IMongoDatabase database) { this._productCollection = database.GetCollection<Entities.Product>("products"); }
-
A
_productCollection
segítségével már tudunk lekérdező/listázó utasításokat írni. Valósítsuk meg először aListProducts
függvényt. Ez a függvény két lépésből áll: először lekérdezzük az adatbázisból a termékek listáját, majd pedig átkonvertáljuk az elvártModels.Product
osztály elemekből álló listára.A lekérdezés a következőképpen néz ki:
var dbProducts = _productCollection .Find(_ => true) // minden terméket listázunk — üres filter .ToList();
Ezt a listát aztán transzformálva adjuk vissza.
return dbProducts .Select(t => new Product { Id = t.Id.ToString(), Name = t.Name, Price = t.Price, Stock = t.Stock }) .ToList();
-
A
FindProduct(string id)
függvény megvalósítása nagyon hasonlít az előzőhöz, csupán annyiban különbözik, hogy itt egyetlen terméket kérdezünk le,id
alapján. Ügyeljünk rá, hogy azid
-t szövegként kapjuk, ígyObjectId
-vá kell alakítani.A modellé konvertáló lépés ugyanúgy megmarad. Ebben az esetben oda kell figyelnünk azonban, hogy ha nem találjuk az adott terméket, akkor adjunk vissza
null
értéket, ne próbáljunk konvertálni.A lekérdező lépés a következőre módosul:
var dbProduct = _productCollection .Find(t => t.Id == ObjectId.Parse(id)) .SingleOrDefault(); // ... model konverzio
Figyeljük itt meg, hogy hogyan módosult a filter kifejezés! Fontos továbbá, hogy itt
ToList
helyett aSingleOrDefault
kiértékelő kifejezést használjuk. Ez a megszokott módon vagy egy konkrét terméket ad vissza, vagynull
értéket. Így tudunk tehátId
alapján megtalálni egy entitást az adatbázisban. Jegyezzük ezt meg, mert ez még sok következő feladatban hasznos lesz!A konvertáló kifejezést már megírtuk egyszer az előző kifejezésben, ezt használhatjuk itt is — figyeljünk azonban oda, hogy a
dbProduct
értéke lehetnull
is. Ebben az esetben ne konvertáljunk, csupán adjunk visszanull
értéket mi is. -
Próbáld ki a megírt függvények működését! Indítsd el a programot, és navigálj tetszőleges böngészőben a http://localhost:5000 weboldalra. Itt a
Products
menüpontban már látnod kell a termékeket felsoroló táblázatot. Ha valamelyik sorban aDetails
menüpontra kattintasz, akkor egy adott termék részleteit is látnod kell.
Ha nem látsz egyetlen terméket se
Ha a weboldalon egyetlen termék se jelenik meg, de az oldal betöltésre kerül és nincs hiba, akkor az adatbázis elérésével van probléma. Valószínűleg nem létezik a megadott nevű adatbázis. Lásd fentebb az adatbázis konfigurálását.
Létrehozás¶
-
Ebben a pontban az
InsertProduct(Product product)
függvényt valósítjuk meg. A bemenőModels.Product
modell adatait a felhasználó szolgáltatja a felhasználói felületen keresztül. -
Egy termék létrehozásához először létre kell hoznunk egy új adatbázisentitás objektumot. Jelen esetben ez egy
Entites.Product
objektum lesz. AzId
értéket nem kell megadnunk — ezt majd az adatbázis generálja. AName
,Price
ésStock
értékeket a felhasználó szolgáltatja. Két érték maradt ki: azVat
és aCategoryId
. Az előbbinek adjunk tetszőleges értéket, az utóbbinak pedig keressünk egy szimpatikus kategóriát az adatbázisban a Studio 3T segítségével, és annak az_id
értékét drótozzuk be!var dbProduct = new Entities.Product { Name = product.Name, Price = product.Price, Stock = product.Stock, Vat = new Entities.Vat { Name = "General", Percentage = 20 }, CategoryId = ObjectId.Parse("5d7e4370cffa8e1030fd2d99"), }; _productCollection.InsertOne(dbProduct);
Ha megvan az adatbázisentitás objektum, akkor az
InsertOne
utasítás segítségével tudjuk elmenteni az adatbázisba. -
A függvény kipróbálásához indítsd el megint a programot, és a termékek táblázata feletti
Add new product
linkre kattints. Itt meg tudod adni a szükséges adatokat, amivel meghívódik a kódod.
Törlés¶
-
A törlés megvalósításához a
DeleteProduct(string id)
függvényt kell implementálni. Itt a kollekcióDeleteOne
függvényét kell használni. Ehhez meg kell adni egy filter kifejezést: itt használjuk ugyanazt a filtert, amit az egy konkrét termék lekérdezéséhez használtunk aFindProduct(string id)
metódusban. -
Ezt a metódust is ki tudod próbálni, ha a termékek táblázatában valamelyik sorban a
Delete
linkre kattintasz.
Módosítás¶
-
A termékek módosító utasításaként az eladást fogjuk megvalósítani, a
bool SellProduct(string id, int amount)
függvényben. A függvény akkor és csak akkor térjen visszatrue
értékkel, ha létezik azid
azonosítójú termék, és legalábbamount
darab van belőle raktáron, amit el is tudtunk adni. Ha nem létezik a termék vagy nincs belőle elegendő, akkor térjen visszafalse
értékkel. -
A MongoDB atomicitását kihasználva ezt a feladatot egyetlen utasítás kiadásával fogjuk megvalósítani. A filter kifejezésben fogunk rászűrni a megadott
id
-ra, és arra is, hogy elegendő termék van-e raktáron. A módosító kifejezésben fogjuk csökkenteni a raktárkészletet — csak akkor, ha létezik a termék, és elegendő van belőle raktáron.var result = _productCollection.UpdateOne( filter: t => t.Id == ObjectId.Parse(id) && t.Stock >= amount, update: Builders<Entities.Product>.Update.Inc(t => t.Stock, -amount), options: new UpdateOptions { IsUpsert = false });
Fontos megfigyelni, hogy az
UpdateOptions
segítségével jeleztük az adatbázisnak, hogy NE upsertet hajtson végre — tehát ne tegyen semmit ha nem találja a filterben megadott terméket.A módosító utasítást a
Builders
-ben találhatóUpdate
builder segítségével tudjuk összerakni. Esetünkbenamount
-tal akarjuk csökkenteni az értéket — ez-amount
-tal történő inkrementálást jelent.A visszatérési értéket az update
result
-jából tudjuk meghatározni. Amennyiben talált olyan terméket, ami megfelelt a filternek, akkor sikeres volt a módosítás, teháttrue
értékkel térhetünk vissza. Egyébként a visszatérési értékfalse
.return result.MatchedCount > 0;
-
Ezt a metódust is ki tudod próbálni, ha a termékek táblázatában valamelyik sorban a
Buy
linkre kattintasz. Próbáld ki úgy is, ha túl nagy értéket írsz be!
BEADANDÓ
Készíts egy képernyőképet a termék listázó weboldalról miután felvettél legalább egy új terméket. A képet a megoldásban f1.png
néven add be. A képernyőképen látszódjon a termék lista. Ellenőrizd, hogy a Neptun kódod (az oldal aljáról) látható-e a képen! A képernyőkép szükséges feltétele a pontszám megszerzésének.
2. Feladat: Kategóriák listázása (4 pont)¶
Ebben a feladatban a kategóriákat fogjuk listázni — az adott kategóriába tartozó termékek számával együtt. Ehhez már aggregációs utasítást is használnunk kell majd. Továbbra is a Dal.Repository
osztályba dolgozunk.
A megvalósítandó függvény a IList<Category> ListCategories()
. Ennek minden kategóriát vissza kell adnia. A Models.Category
osztály 3 adattagot tartalmaz.
Name
: értelemszerűen a kategória neveParentCategoryName
: a kategória szülőkategóriájának neve. Amennyiben nincs szülőkategória, értéke legyennull
.NumberOfProducts
: a kategóriába tartozó termékek száma. Amennyiben nincs ilyen, értéke legyen 0.
A megvalósítás lépései a következők.
-
Első lépésként a
_productCollection
mintájára vedd fel és inicializáld a_categoryCollection
-t is. Az adatbázisban a kollekció nevecategories
— ezt Studio 3T segítségével tudod ellenőrizni. -
A
ListCategories()
metódusban először kérdezzük le a kategóriák teljes listáját. Ez pontosan ugyanúgy történik, mint az előző feladatban a termékek esetében. A lekérdezés értékét tegyük adbCategories
változóba. -
Ezután kérdezzük le, hogy az egyes
CategoryId
-khez hány darab termék tartozik. Ehhez aggregációs pipeline-t kell használnunk, azon belül pedig a$group
lépést.var productCounts = _productCollection .Aggregate() .Group(t => t.CategoryId, g => new { CategoryID = g.Key, NumberOfProducts = g.Count() }) .ToList();
Ez az utasítás egy olyan listával tér vissza, melyben minden elem egy
CategoryID
értéket tartalmaz a hozzá tartozó termékek számával együtt. -
Ezen a ponton minden számunkra szükséges információ rendelkezésünkre áll — ismerjük az összes kategóriát (a szülőkategória megkereséséhez), és ismerjük a kategóriákhoz tartozó termékek számát. Egyetlen dolgunk van, hogy ezeket az információkat (C# kódból) "összefésüljük".
return dbCategories .Select(k => new Category { Name = k.Name, ParentCategoryName = k.ParentCategoryId.HasValue ? dbCategories.Single(p => p.Id == k.ParentCategoryId.Value).Name : null, NumberOfProducts = productCounts.SingleOrDefault(pc => pc.CategoryID == k.Id)?.NumberOfProducts ?? 0 }) .ToList();
Láthatjuk, hogy mind a két lépést egyszerűen elintézhetjük C#-ban LINQ segítségével. A szülőkategória nevéhez a kategóriák között kell keresnünk, a termékek darabszámához pedig az aggregáció eredményében keresünk.
Join Mongo-ban
Nem ez az egyetlen módja a gyűjtemények "összekapcsolásának" MongoDB-ben. Ugyan
join
nincs, de léteznek megoldások a gyűjteményeken átívelő lekérdezésekre. A fenti megoldás az adatbázis helyett C# kódban végzi el az összekapcsolást. Ez akkor praktikus, ha nem nagy méretű adathalmazzal dolgozunk, és nincs (jó) szűrésünk. Ha szűrni kellene az adathalmazt, a fenti megoldás is bonyolultabb lenne a hatékonyság érdekében. -
A kód kipróbálásához a weboldal
Categories
menüpontjára kell navigálni. Itt táblázatos formában megjelenítve láthatod az összegyűjtött információkat. Teszteléshez alkalmazhatod az előző feladatban elkészítettAdd new product
funkciót — itt a hozzáadás esetén az egyik kategória mellett növekednie kell a hozzá tartozó termékek darabszámának. (A termék beszúrásakor a kategória ID-ját bedrótoztuk a kódba, tehát annak a kategóriának kell nőnie, amelyiknek az ID-ja a kódban szerepel.)
BEADANDÓ
Készíts egy képernyőképet a kategória listázó weboldalról. A képet a megoldásban f2.png
néven add be. A képernyőképen látszódjon a kategória lista. Ellenőrizd, hogy a Neptun kódod (az oldal aljáról) látható-e a képen! A képernyőkép szükséges feltétele a pontszám megszerzésének.
3. Feladat: Megrendelések lekérdezése és módosítása (5 pont)¶
Ebben a feladatban a Megrendelés (Order
) entitáshoz tartozó CRUD (létrehozás, listázás/olvasás, módosítás és törlés) utasításokat fogjuk megvalósítani. Ez a feladat nagyon hasonlít az első feladathoz, amennyiben elakadnál nyugodtan meríts ihletet az ottani megoldásokból!
A Models.Order
entitás adattagjai:
Id
: az adatbázisentitásId
-ja,ToString
-gel sorosítvaDate
,Deadline
,Status
: egy az egyben másolandók az adatbázis entitásbólPaymentMethod
: az adatbázis entitásban találhatóPaymentMethod
komplex objektumMethod
mezőjeTotal
: a megrendelésben található tételek (OrderItems
)Amount
ésPrice
szorzatainak összege
Ennek a feladatnak a megoldásához a megrendeléssel kapcsolatos metódusok implementációja szükséges (ListOrders
, FindOrder
, InsertOrder
, DeleteOrder
és UpdateOrder
).
Az alábbi feladatok előtt ne felejtsd el felvenni és inicializálni a _orderCollection
-t a repository osztályba a korábban látottak mintájára!
Listázás/olvasás¶
-
A
ListOrders
függvény paraméterként kap egystring status
értéket. Ha ez az érték üres vagynull
(lásd:string.IsNullOrEmpty
), akkor minden megrendelést listázz. Ellenkező esetben csak azokat a megrendeléseket listázd, melyeknek aStatus
értéke teljesen egyezik a paraméterben érkezőstatus
értékkel. -
A
FindOrder
metódus egy konkrét megrendelés adatait adja vissza astring id
érték alapján szűrve. Figyelj oda, ha az adottID
érték nem található az adatbázisban, akkornull
értéket adj vissza!
Létrehozás¶
-
Az
InsertOrder
metódusban a létrehozást kell megvalósítanod. Ehhez háromféle információt kapsz:Order order
,Product product
ésint amount
. -
Az adatbázisentitás létrehozásához a következő információkra van szükség:
CustomerId
,SiteId
: az adatbázisból keresd ki egy tetszőleges vevőhöz (Customer
) tartozó dokumentum_id
ésmainSiteId
értékét. Ezeket az értékeket drótozd bele a kódodba.Date
,Deadline
,Status
: ezeket az értékeket azorder
paraméterből vehetedPaymentMethod
: hozz létre egy újPaymentMethod
objektumot. AMethod
legyen azorder
paraméterben találhatóPaymentMethod
érték. ADeadline
maradjonnull
!OrderItems
: egyetlen tételt hozz létre! Ennek adattagjai:ProductId
ésPrice
: aproduct
paraméterből vehetedAmount
: a függvényparaméteramount
paraméterből jönStatus
: azorder
paraméterStatus
mezőjével egyezik meg
- minden más adattag (a számlázással kapcsolatos információk) maradjon
null
értéken!
Törlés¶
A DeleteOrder
törölje a megadott Id
-hoz tartozó megrendelést.
Módosítás¶
A módosító utasításban (UpdateOrder
) arra figyelj oda, hogy csak azokat a mezőket írd felül, melyek a Models.Order
osztályban megtalálhatóak: Date
, Deadline
, Status
és PaymentMethod
. Az Total
-t itt nem kell figyelembe venni, ennek értéke nem fog változni.
Tipp
Több módosító kifejezést a Builders<Entities.Order>.Update.Combine
segítségével lehet összevonni.
Itt is figyelj oda, hogy az update során az IsUpsert
beállítás értéke legyen false
!
A metódus visszatérési értéke akkor és csak akkor legyen true
, ha létezik megrendelés a megadott ID
-val — azaz volt illeszkedés a filterre.
Kipróbálás¶
A megírt függvényeket a weboldalon a Orders
menüpont alatt tudod kipróbálni. Teszteld le a Filter
, Add new order
, Edit
, Details
és Delete
opciókat is!
BEADANDÓ
Készíts egy képernyőképet a megrendelés listázó weboldalról miután felvettél legalább egy új megrendelést. A képet a megoldásban f3.png
néven add be. A képernyőképen látszódjon a megrendelések listája. Ellenőrizd, hogy a Neptun kódod (az oldal aljáról) látható-e a képen! A képernyőkép szükséges feltétele a pontszám megszerzésének.
4. Feladat: Vevők listázása (4 pont)¶
Ebben a feladatban a vevőket fogjuk listázni — az általuk megrendelt termékek összértékével együtt. Ehhez a második feladathoz hasonlatosan aggregációs utasítást és C# kódban történő "összefésülést" kell majd használnunk.
A megvalósítandó metódus az IList<Customer> ListCustomers()
. Ennek minden vevőt vissza kell adnia. A Models.Customer
entitás adattagjai:
Name
: a vevő neveZipCode
,City
,Street
: a vevő központi telephelyéhez tartozó címTotalOrders
: a vevőhöz tartozó összes megrendelés összértékének (lásd előző feladat) összege. Amennyiben még nincs az adott vevőhöz tartozó megrendelés, akkor ennek az értéke legyennull
!
A feladat megoldásához ajánlott lépések:
-
Vedd fel és inicializáld a
_customerCollection
-t! -
Listázd ki az összes vevőt. A vevő entitásban megtalálod a telephelyek listáját (
Sites
) és a központi telephely azonosítóját (MainSiteId
) is. Ez utóbbit kell megkeresned az előbbi listában, hogy megkapd a központi telephelyet (és így a hozzá tartozó címet). -
A megrendelések kollekcióján aggregációs pipeline-t használva meg tudod állapítani az adott
CustomerId
-hez tartozó összmegrendelések értékét. -
Végezetül csak a meglevő információkat kell "összefésülnöd". Központi telephelye minden vevőnek van, viszont megrendelése nem garantált — figyelj oda, hogy ekkor a
TotalOrders
elvárt értékenull
! -
A kód kipróbálásához a weboldal
Customers
menüpontjára kell navigálni. Itt táblázatos formában megjelenítve láthatod az összegyűjtött információkat. Teszteléshez alkalmazhatod az előző feladatban elkészítettAdd new order
funkciót — itt új megrendelés felvétele esetén az előző feladatban bedrótozott vevő mellett növekednie kell a hozzá tartozó megrendelések összértékének.
BEADANDÓ
Készíts egy képernyőképet a vevő listázó weboldalról. A képet a megoldásban f4.png
néven add be. A képernyőképen látszódjon a vevők listája. Ellenőrizd, hogy a Neptun kódod (az oldal aljáról) látható-e a képen! A képernyőkép szükséges feltétele a pontszám megszerzésének.
5. Feladat: Opcionális (iMSc) feladat (3 iMsc pont)¶
Ebben a feladatban az adatbázisban található megrendeléseket fogjuk dátum szerint csoportosítani — kíváncsiak vagyunk ugyanis az elmúlt időszakokban a megrendelések mennyiségének és összértékének alakulására. Ennek megvalósításához a $bucket
aggregációs lépést fogjuk használni.
Követelmények¶
A megvalósítandó metódus az OrderGroups GroupOrders(int groupsCount)
. Ez az adatbázisban található megrendeléseket groupsCount
egyenlő időintervallumra csoportosítja. A visszatérési érték két adattagot tartalmaz:
IList<DateTime> Thresholds
: Az időpontok amik az időintervallumok határait jelentik.- Az intervallumok alsó határa inkluzív, a felső határ exkluzív
n
darab intervallum esetén aThresholds
listan + 1
elemű- Pl.: Ha a
Thresholds
lista elemeia, b, c, d
, akkor az időintervallumok a következők:[a, b[
,[b, c[
és[c, d[
.
IList<OrderGroup> Groups
: A megrendelések csoportjai. AOrderGroup
entitás adattagjai:Date
: Az adott intervallum kezdő dátuma. Tehát[a, b[
intervallum eseténa
.Pieces
: Az adott intervallumba eső megrendelések darabszáma.Total
: Az adott intervallumba tartozó összes megrendelés összértékének összege (lásd előző feladat).
További követelmények:
- Pontosan
groupsCount
intervallumra bontsd a megrendeléseket.- A
Thresholds
lista elemszáma így pontosangroupsCount + 1
. - A
Groups
elemszáma legfeljebbgroupsCount
— az üres (megrendelést nem tartalmazó) intervallumoknak nem kell listaelem
- A
- A legelső határ legyen az adatbázisban található legrégebbi megrendelés dátuma
- A legutolsó határ legyen az adatbázisban található legújabb megrendelés dátuma + 1 óra
- Ez azért kell, mert az intervallum felső határa exkluzív. Így garantáljuk, hogy az adatbázisban található minden megrendelés belekerül egy intervallumba.
- Tipp: a következő módon tudsz egy órát hozzáadni egy dátumhoz:
date.AddHours(1)
.
- Az intervallumok legyenek egyenlő méretűek
- Tipp: a C# nyelv beépítve kezeli matematikai műveletek végzését dátum (
DateTime
) és időtartam (TimeSpan
) objektumokon — lásd pl. előző pont.
- Tipp: a C# nyelv beépítve kezeli matematikai műveletek végzését dátum (
A megoldás során feltételezheted a következőket:
- Az adatbázisban található minden megrendelésnek van
Date
értéke, annak ellenére, hogy az adattag típusa nullable (DateTime?
).- Használd tehát nyugodtan a
date.Value
értéket adate.HasValue
érték ellenőrzése nélkül.
- Használd tehát nyugodtan a
- A
groupsCount
egy pozitív egész szám (tehát értéke legalább 1).
Megoldás vázlata¶
-
Kérdezd le az adatbázisból a legrégebbi és a legújabb megrendelés dátumát.
- Tipp: Ezt megoldhatod két lekérdezéssel vagy akár egyetlen aggregáció segítségével is.
-
Számold ki az intervallumok határait a követelményeknek megfelelően.
- Ezzel már meg is fogod kapni a visszatérési értékben szükséges
Thresholds
listát.
- Ezzel már meg is fogod kapni a visszatérési értékben szükséges
-
A megrendelések kollekción hajts végre egy
$bucket
aggregációt. Ennek dokumentációját itt találhatod meg.- a
groupBy
kifejezés a megrendelés dátuma lesz - a
boundaries
kifejezés pontosan abban a formában várja az értékeket, amit a követelmények között is olvashattál, tehát az előző pontban előállított lista pontosan megfelel - az
output
kifejezésben fogalmazhatod meg a szükséges kiszámolandó értékeket (darabszám, összérték)
Tipp
Ha
"Element '...' does not match any field or property of class..."
kezdetű exceptiont kapsz, akkor azoutput
kifejezésben írj át minden property-t kisbetűsre (pl.:Pieces
->pieces
). Úgy tűnik, hogy a Mongo C# driver ezen a ponton nem konzisztensen transzformálja az adattagok neveit. - a
-
A
$bucket
aggregáció az elvárt követelményeknek pontosan megfelelő intervallumokkal fog visszatérni, így az eredményét már csak transzformálni kell a megfelelőOrderGroup
objektumok listájává, majd pedig előállítani a visszatérési értéket. -
A kód kipróbálásához a weboldal
Group orders
menüpontjára kell navigálni. Itt diagramokon megjelenítve láthatod az összegyűjtött információkat. Tesztelés során módosítsd a csoportok számát, és vegyél fel új megrendeléseket különböző dátumokkal korábbi feladatokban elkészítettAdd new order
segítségével!
BEADANDÓ
Készíts egy képernyőképet a diagramokat mutató weboldalról. A képet a megoldásban f5.png
néven add be. A képernyőképen látszódjon a két diagram (ehhez csökkentsd a böngészőben a nagyítást, hogy kiférjenek egy képernyőre). Ellenőrizd, hogy a Neptun kódod (az oldal aljáról) látható-e a képen! A képernyőkép szükséges feltétele a pontszám megszerzésének.