Pokud chceme zobrazovat nejčtenější články všech dob, není to nic složitého. Stačí do tabulky článků přidat sloupec čtenost a aktualizovat ho při každém zobrazení článku (s MyISAM tabulkami je vhodné použít UPDATE LOW_PRIORITY). Pokud nad tento sloupec přidáme index, tak se podle něj bude i rychle řadit.
Se zobrazením článků za pevné období (např. po dnech) také není problém. Stačí vytvořit tabulku clanky_ctenost (clanek, datum, ctenost)
s unikátním klíčem nad (clanek, datum)
a aktualizovat ji pomocí ON DUPLICATE KEY UPDATE. Při existenci indexu nad (datum, ctenost)
bude získání nejčtenějších článků v konkrétním dni opět rychlé.
Složitější je získání nejčtenějších článků za nějaké plovoucí období (např. za posledních 7 dní). K tomu samozřejmě také můžeme použít předchozí tabulku, problém je ale ten, že pro dotaz WHERE datum >= CURDATE() - INTERVAL 7 DAY GROUP BY clanek ORDER BY SUM(ctenost) DESC LIMIT 10
nelze vytvořit index, takže pokud je článků hodně, bude tento dotaz pomalý.
Můžeme samozřejmě udělat to, že do tabulky článků přidáme sloupec ctenost_tyden
, který budeme aktualizovat spolu s tabulkou clanky_ctenost
při každém přístupu a z kterého jednou denně odečteme osm dní staré přístupy. V MySQL 5.1 k tomu lze použít podporu pravidelných událostí, se staršími verzemi je nutné použít cron.
Nevýhoda tohoto řešení spočívá v tom, že jednak závisí na pravidelném provádění nějakého úkonu a jednak potřebuje tabulku clanky_ctenost
. Přemýšlel jsem proto o nějakém elegantnějším řešení. To lze použít v případě, že nás nezajímá čtenost přesně za poslední týden, ale stačí nám poněkud vágnější „poslední dobou“.
Myšlenka řešení spočívá v tom, že čím novější přístup, tím za něj započteme víc bodů. Konkrétně třeba takovýmto vzorcem: pow(1.2, time() / 60 / 60 / 24 - 49 * 365)
. Pokud o tuto hodnotu zvýšíme popularitu článku při každém přístupu, tak bude vyjadřovat jeho oblíbenost v poslední době – čím novější přístup, tím hodnotnější. Např. 100 přístupů dnes má stejnou hodnotu jako 358 přístupů před týdnem nebo 23738 přístupů před měsícem. Hodnota 1.2 vyjadřuje, jak rychle chceme čtenost zastarávat, magická konstanta 49 udržuje číslo v rozsahu povoleném v PHP a v MySQL u datového typu double (od E-308
do E+308
). Při zvýšení hodnoty 1.2 by bylo potřeba tuto konstantu změnit a vzorec čas od času oprášit (v této podobě vydrží asi 20 let).
<?php $popularita = pow(1.2, time() / 60 / 60 / 24 - 49 * 365); mysql_query("UPDATE LOW_PRIORITY clanky SET nedavna_popularita = nedavna_popularita + $popularita WHERE id = $id"); ?>
Diskuse je zrušena z důvodu spamu.