ИЕП/К1 2020

Извор: SI Wiki
Пређи на навигацију Пређи на претрагу

Први колоквијум 2020. године оригинално није био доступан, али је професор Милош Цветановић на консултацијама одржаним 25. марта 2022. године поделио поставку овог колоквијума са студентима као вежбу пред колоквијум.

Поставка

Компанија поседује већи број дистрибутера и производа који су или лекови или не-лек препарати. За не-лек препарат се може одређеном дистрибутеру одобрити рекламирање. Дистрибутери и апотеке склапају специјалне уговоре о међусобној сарадњи (прати се датум потписивања), при чему постоји ограничење да једна апотека може склопити максимално један такав уговор. На основу тог уговора апотека добија право на попуст на један лек. Након оваквог уговора може, а не мора да се, једном годишње формира извештај о оствареној продаји у тој апотеци.

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 - Лек, N - Не-лек

  1. Навести по један пример сваког документа уколико би се за потребе наведене евиденције користила база података заснована на документима (mongoDB), али тако да модел искористи све предности нерелационог модела података.
  2. Саставити скрипт који користећи функцију за агрегацију (aggregation framework) враћа шифре и називе оних апотека које имају уговор након 2000 године, а при томе имају и више од 3 извештаја са износом преко милион.
  3. Саставити Map/Reduce посао који за сваки датум који се појављује у евиденцији уговора враћа информацију о просечном броју евидентираних извештаја.

1. задатак

Дистрибутер

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

Производ

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

Апотека

{
    "_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. задатак

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. задатак

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
});

Тестирање

Решења изнад можете тестирати над следећом базом:

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
        }
    },
    // ...
]);