IEP/K1 2020

Izvor: SI Wiki
Pređi na navigaciju Pređi na pretragu

Prvi kolokvijum 2020. godine originalno nije bio dostupan, ali je profesor Miloš Cvetanović na konsultacijama održanim 25. marta 2022. godine podelio postavku ovog kolokvijuma sa studentima kao vežbu pred kolokvijum.

Postavka

Kompanija poseduje veći broj distributera i proizvoda koji su ili lekovi ili ne-lek preparati. Za ne-lek preparat se može određenom distributeru odobriti reklamiranje. Distributeri i apoteke sklapaju specijalne ugovore o međusobnoj saradnji (prati se datum potpisivanja), pri čemu postoji ograničenje da jedna apoteka može sklopiti maksimalno jedan takav ugovor. Na osnovu tog ugovora apoteka dobija pravo na popust na jedan lek. Nakon ovakvog ugovora može, a ne mora da se, jednom godišnje formira izveštaj o ostvarenoj prodaji u toj apoteci.

DISTRIBUTER (SifD, Naziv, Adresa, PIB)
PROIZVOD (SifP, StaJe, Naziv, Cena)
LEK (SifP, Licenca)
NE-LEK (SifP, Opis)
APOTEKA (SifA, Naziv, Adresa)
UGOVOR (SifU, Datum, SifD, SifA)
IZVESTAJ (SifI, Iznos, SifU)
REKLAMIRA (SifP, SifD)
POPUST (SifU, SifP)

StaJe: L - Lek, N - Ne-lek

  1. Navesti po jedan primer svakog dokumenta ukoliko bi se za potrebe navedene evidencije koristila baza podataka zasnovana na dokumentima (mongoDB), ali tako da model iskoristi sve prednosti nerelacionog modela podataka.
  2. Sastaviti skript koji koristeći funkciju za agregaciju (aggregation framework) vraća šifre i nazive onih apoteka koje imaju ugovor nakon 2000 godine, a pri tome imaju i više od 3 izveštaja sa iznosom preko milion.
  3. Sastaviti Map/Reduce posao koji za svaki datum koji se pojavljuje u evidenciji ugovora vraća informaciju o prosečnom broju evidentiranih izveštaja.

1. zadatak

Distributer

{
    "_id": 1,
    "Naziv": "Kompanija",
    "Adresa": "Ulica 1, Grad",
    "PIB": 121241231231
}

Proizvod

{
    "_id": 1,
    "StaJe": "L",
    "Naziv": "Lek 1",
    "Cena": 123,
    // Lek
    "Licenca": "Neka",
    // Ne-lek
    "Opis": null,
    // Reklamira
    "DistributerReklamira": null
}

Apoteka

{
    "_id": 1,
    "Naziv": "Apoteka 1",
    "Adresa": "Ulica 2, Grad",
    // Ugovor
    "Ugovor": {
        "SifU": 1,
        "Datum": "2022-03-25T10:39:55Z",
        "SifD": 1,
        // Izvestaj
        "Izvestaji": [
            {
                "SifI": 1,
                "Iznos": 123
            }
        ],
        // Popust
        "PopustNaLek": 1
    }
}

2. zadatak

db.apoteka.aggregate([
    {
        $addFields: {
            Godina: {
                $year: {
                    $dateFromString: {
                        dateString: '$Ugovor.Datum',
                        format: '%Y-%m-%dT%H:%M:%SZ'
                    }
                }
            }
        }
    },
    {
        $match: {
            Godina: {
                $gt: 2000
            }
        }
    },
    {
        $unwind: '$Ugovor.Izvestaji',
    },
    {
        $match: {
            'Ugovor.Izvestaji.Iznos': {
                $gt: 1_000_000
            }
        }
    },
    {
        $group: {
            _id: '$_id',
            Izvestaji: {
                $count: {}
            },
            Naziv: {
                $first: '$Naziv'
            }
        }
    },
    {
        $match: {
            Izvestaji: {
                $gt: 3
            }
        }
    },
    {
        $project: {
            _id: 0,
            Sifra: '$_id',
            Naziv: '$Naziv'
        }
    }
]);

3. zadatak

function map() {
    emit(this.Ugovor.Datum, {
        count: 1,
        sum: this.Ugovor.Izvestaji.length,
        avg: 0
    });
}

function reduce(datum, values) {
    return {
        count: Array.sum(values.map(v => v.count)),
        sum: Array.sum(values.map(v => v.sum)),
        avg: 0
    };
}

function finalize(datum, value) {
    value.avg = value.sum / value.count;
    return value;
}

db.apoteka.mapReduce(map, reduce, {
    out: 'k1_2020_c',
    finalize
});

Testiranje

Rešenja iznad možete testirati nad sledećom bazom:

db.createCollection('apoteka');
db.apoteka.insertMany([
    {
        _id: 1,
        Naziv: 'Apoteka 1',
        Adresa: 'Ulica 2, Grad',
        Ugovor: {
            SifU: 1,
            Datum: '2022-03-25T10:39:55Z',
            SifD: 1,
            Izvestaji: [
                {
                    SifI: 1,
                    Iznos: 1_000_001
                },
                {
                    SifI: 2,
                    Iznos: 1_000_001
                },
                {
                    SifI: 3,
                    Iznos: 1_000_001
                },
                {
                    SifI: 4,
                    Iznos: 1_000_001
                }
            ],
            PopustNaLek: 1
        }
    },
    // ...
]);