wiki:AdvancedApplicationDevelopment

Version 2 (modified by 223270, 3 days ago) ( diff )

--

Напреден апликативен развој

Имплементирани се сите случаи на употреба дефинирани во фаза 3.

Примери на индекси

Индексите се користат за да се забрза извршувањето на често користени SELECT, JOIN и WHERE. Со оглед на тоа што во Travel Sage често пребаруваме активности според датум и корисник, се додаваат индекси врз тие колони.

  • За побрзо пребарување на активности во одреден период
    CREATE INDEX idx_aktivnost_datum ON aktivnosti(datum_od, datum_do);
    
  • За побрз join и филтрирање по корисник при резервации
    CREATE INDEX idx_rezervacii_korisnik ON rezervacii(idkorisnik);
    
  • За побрзо пребарување на дестинации по име на локација
    CREATE INDEX idx_destinacii_lokacija ON destinacii(imelokacija);
    

Примери за тригери

Тригерите се користат за автоматска реакција на промена во базата. Во TravelSage, тие се применети за: контрола на интегритет (нема дупли препораки) и автоматска реакција на негативна рецензија.

  1. Спречување дупли препораки
    CREATE OR REPLACE FUNCTION prevent_duplicate_recommendation()
    RETURNS TRIGGER AS $$
    BEGIN
       IF EXISTS (
           SELECT 1 FROM preporaki
           WHERE idkorisnik = NEW.idkorisnik AND iddestinacija = NEW.iddestinacija
       ) THEN
           RAISE EXCEPTION 'User already has this destination in recommendations!';
       END IF;
       RETURN NEW;
    END;
    $$ LANGUAGE plpgsql;
    
    CREATE TRIGGER trg_check_duplicate_recommendation
    BEFORE INSERT ON preporaki
    FOR EACH ROW EXECUTE FUNCTION prevent_duplicate_recommendation();
    
  1. Деактивирање дестинација со негативни рецензии
    CREATE OR REPLACE FUNCTION check_negative_review()
    RETURNS TRIGGER AS $$
    BEGIN
       IF NEW.ocenka < 3 THEN
           UPDATE destinacii
           SET aktivna = FALSE
           WHERE iddest = NEW.iddest;
       END IF;
       RETURN NEW;
    END;
    $$ LANGUAGE plpgsql;
    
    CREATE TRIGGER trg_negative_review
    AFTER INSERT ON recenzii
    FOR EACH ROW EXECUTE FUNCTION check_negative_review();
    

Примери за прегледи

View се користи за да се поедностават комплексни пребарувања.

  1. Во TravelSage, прикажани се активности што се „најдобра вредност за пари“, базирано на цена и просечна оцена од рецензии.
    CREATE VIEW best_value_activities AS
    SELECT 
        a.idaktivnost, 
        a.ime, 
        a.iznos, 
        d.imelokacija, 
        AVG(r.ocenka) AS avg_rating
    FROM aktivnosti a
    JOIN destinacii d ON a.iddest = d.iddest
    JOIN recenzii r ON a.idaktivnost = r.idaktivnost
    GROUP BY a.idaktivnost, a.ime, a.iznos, d.imelokacija
    HAVING AVG(r.ocenka) > 4 AND a.iznos < 1000;
    
  2. Активности со најниски цени
     DB::statement("
                CREATE VIEW view_procent_cheap_destinations AS
                SELECT
                    d.imelokacija,
                    COUNT(CASE WHEN a.iznos < 500 THEN 1 END) * 100.0 / COUNT(*) AS procent_cheap
                FROM travel_sage.destinacii d
                JOIN travel_sage.aktivnosti a ON d.iddest = a.iddest
                GROUP BY d.iddest, d.imelokacija
                ORDER BY procent_cheap DESC
            ");
    

Трансакции

  1. Пример при резервација на активност
    DB::transaction(function () use ($request) {
        DB::table('rezervacii')->insert([
            'idkorisnik' => auth()->id(),
            'idaktivnost' => $request->aktivnost_id,
            'datum' => now()
        ]);
    
        DB::table('aktivnosti')
            ->where('idaktivnost', $request->aktivnost_id)
            ->decrement('kvota', 1);
    });
    

Ако не успее било кој дел (резервација или ажурирање на квота), не се зачувува ништо – атомичност.

  1. DB::transaction(function () use ($request) {
                $validatedData = $request->validate([
                    'imepaket' => 'required|string|max:255',
                    'cena' => 'required|numeric',
                    'pochetok' => 'required|date_format:Y-m-d\TH:i',
                    'kraj' => 'required|date_format:Y-m-d\TH:i|after_or_equal:pochetok',
                ]);
    
                TravelPackage::create($validatedData);
            });
    
  1. DB::transaction(function () use ($request) {
                $validatedData = $request->validate([
                    'naziv' => 'required|string|max:255',
                    'vidovi' => 'required|string|max:255',
                    'detali' => 'nullable|string',
                    'pochetendatum' => 'required|date',
                    'kraendatum' => 'required|date',
                ]);
    
                TravelEvent::create($validatedData);
            });
    
  1. DB::transaction(function () use ($request) {
                $validatedData = $request->validate([
                    'imeaktivnost' => 'required|string|max:255',
                    'informacii' => 'nullable|string|max:255',
                    'kategorija' => 'required|string|max:255',
                    'iznos' => 'nullable|numeric',
                ]);
    
                TravelActivity::create($validatedData);
            });
    

Складирани функции и процедури

  1. Просечна оцена за локација (функција)
    CREATE OR REPLACE FUNCTION avg_rating_for_location(dest_id INT)
    RETURNS FLOAT AS $$
    DECLARE
        result FLOAT;
    BEGIN
        SELECT AVG(ocenka)
        INTO result
        FROM recenzii
        WHERE iddest = dest_id;
        RETURN result;
    END;
    $$ LANGUAGE plpgsql;
    
  1. Додади препорака (процедура)
    CREATE OR REPLACE PROCEDURE dodadi_preporaka(p_korisnik INT, p_dest INT)
    LANGUAGE plpgsql
    AS $$
    BEGIN
        INSERT INTO preporaki(idkorisnik, iddestinacija, datum)
        VALUES (p_korisnik, p_dest, NOW());
    END;
    $$;
    

Овие складирани елементи се користат за централизирана логика и можат да се повикаат од Laravel или други процедури.

Note: See TracWiki for help on using the wiki.