Toon posts:

[MySQL] user aanbevelingen ahv data andere users

Pagina: 1
Acties:

Verwijderd

Topicstarter
Via mijn site kunnen verschillende mensen zich registereren en enkele gegevens invoeren. Ik wil op basis van gegevens van andere users de nieuwe user een aanbeveling doen. Maar dat is niet eenvoudig te doen in MySQL. Om het even duidelijk te maken een voorbeeld. Stel je hebt een tabel als:

voorkeur_id (INT,11, auto_increment)
user_id (INT, 11, id van de gebruiker)
voorkeur (VARCHAR, 255)
In 'voorkeur' kan een gebruiker invoeren wat zijn lievelingsfruit is. Je krijgt dan per gebruiker verschillende rijen in de database, met elke keer 1 lievelingsvrucht.

Stel iemand voert in dat hij appels en bananen lekker vind, hoe kan ik dan op basis van de andere gegevens aanraden om ook een sinaasappel te proberen? Immers, de gebruikers die appels en bananen lekker vinden, vinden vaak ook een sinaasappel lekker.

Verwijderd

Topicstarter
Kleine toevoeging: In dit geval kan je nog een querie uit laten voeren die iedereen laat zien die ook appels en bananen hebben ingevoerd en dan het derde meest ingevoerde vrucht weergeven.

Maar als iemand 10 verschillende vruchten heeft ingevoerd, dan zullen er maar weinig zijn die 10 vruchten ook hebben, zodat een 11e kan worden aanbevelen. Dan moet er dus ook gechecked worden met minder vruchten. Maar wat is hierin verstandig om te doen...?

  • djluc
  • Registratie: Oktober 2002
  • Laatst online: 12-02 13:44
Je moet eerst gaan normaliseren, dat is een stuk handiger om mee te beginnen.

Verwijderd

Topicstarter
djluc schreef op woensdag 11 oktober 2006 @ 23:07:
Je moet eerst gaan normaliseren, dat is een stuk handiger om mee te beginnen.
Ja, klopt, dat ga ik ook zeker doen. Maar ik wilde het voorbeeld even zo simpel mogelijk maken.

Verwijderd

Topicstarter
Schopje...

Kom er zelf nl. echt niet uit, hoop dat iemand kan helpen.

Verwijderd

Heb je de boel al genormaliseerd? Dus een extra tabel met 1 user/voorkeur record per voorkeur i.p.v. zo'n onhandelbare varchar(255)?
Kan je geen kant en klare voorbeeld queries geven, omdat a) ik niet weet of je MySQL subqueries ondersteunt, b) omdat 't niet helemaal in SQL queries is op te lossen, en c) omdat ik nauwelijks ervaring met MySQL heb. ;)

Ik zou beginnen met een functie/query die de users teruggeeft met (deels) dezelfde voorkeuren, in descending order (meeste overeenkomende voorkeuren eerst). Vervolgens kijken wat die (top 10? top 100?) andere users ook nog prefereren, en die extra voorkeuren wegen op 't aantal keren dat 'ie gevonden wordt.

Ga er maar van uit dat dit meer code (PHP, I assume?) dan query logic vergt.

Verwijderd

Topicstarter
Afterlife, bedankt voor je reply. Lijkt me inderdaad een goede gedachte. Probleem waar ik tegenaan loop is eigenlijk hoe ik gebruikers vind met deels dezelfde voorkeuren.

Met exact dezelfde voorkeuren is duidelijk, maar hoe vind ik iemand die voornamelijk dezelfde voorkeuren heeft. Dat zou betekenen dat ik een hoop queries moet uitvoeren, aangezien er zoveel mogelijkheden zijn. Stel iemand heeft 10 voorkeurvruchten, dan moet ik zoeken naar gebruikers die die 10 ook hebben. Naar gebruikers die 9 van die vruchten heeft (en dat zijn al weer 10 verschillende mogelijkheden van 9 vruchten, etc...

  • whoami
  • Registratie: December 2000
  • Laatst online: 11:29
Haal in één keer alle gebruikers op die gemeenschappelijke voorkeuren heeft als je nieuwe gebruiker, ook al is er maar één. Dat kan je doen met één query.
Dan ga je in je applicatie-logica een algoritme schrijven waarin je een 'matching-percentage' oid berekent, en toon dan de gebruikers die een match hebben van meer dan xx %

https://fgheysels.github.io/


Verwijderd

whoami, dat zei ik toch? :?

[ Voor 46% gewijzigd door Verwijderd op 14-10-2006 15:07 ]


Verwijderd

Topicstarter
Dankzij jullie tips heb ik een redelijk werkend systeem gemaakt. Omdat er nogal wat wordt uitgevoerd, heb ik voor het testen het aantal gebruikers vergroot naar 100.000. En dat blijkt inderdaad teveel te zijn.
Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 35 bytes) in
Probleem is dat de user_id's worden opgeslagen in een array, en die array wordt zo groot dat het geheugen te klein is. Nu kan ik dit geheugen gaan vergroten in php.ini, maar is het niet op een betere manier op te lossen?

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$Q = "SELECT fruit_id FROM floxer_voorkeur WHERE user_id = $id";
$Qresult = mysql_query($Q);
$where_query = "";
while ($r = mysql_fetch_array($Qresult)) {
    $where_query .= " OR fruit_id = $r[0]";
    }
$where_query = "(".substr($where_query,3).")";

$Q = "SELECT user_id FROM floxer_voorkeur WHERE $where_query AND user_id != $id";
$Qresult = mysql_query($Q);
$ov_users = array();
while ($r = mysql_fetch_array($Qresult)) {
    array_push($ov_users,$r[0]);
}

  • whoami
  • Registratie: December 2000
  • Laatst online: 11:29
Hoeveel user id's haal je zo wel op ??

Afterlife: idd; te snel gelezen. :+

https://fgheysels.github.io/


Verwijderd

Lijkt mij dat je 2 mogelijkheden hebt:
1 : je vergroot je geheugen
2 : je topt je query af door het statement LIMIT te gebruiken

  • Anders
  • Registratie: December 2000
  • Laatst online: 05-02 17:26
Verwijderd schreef op zondag 15 oktober 2006 @ 18:52:
Probleem is dat de user_id's worden opgeslagen in een array, en die array wordt zo groot dat het geheugen te klein is.
Lijkt me vanuit performance-oogpunt ook niet zinnig om real-time te werken met alle userdata. Dan kun je op een gegeven moment geheugen blijven bijprikken en dan nog zal je site trager en trager worden. Je zou beter een aparte structuur ernaast kunnen maken en dan bij elke voorkeur opslaan hoeveel gerelateerde voorkeuren er zijn.

bv voorkeur appel:
- banaan 19239
- peer 1583
- meloen 7829
- braam 298

voorkeur banaan
- appel 19239
- peer 13923
- meloen 2302
- braam 1429

Gooi dit in een leuk tabelstructuurtje en het is vrij makkelijk op te vragen zonder dat je veel hoeft te vragen van je processor of geheugen. De data werk je bij zodra gegevens/voorkeuren worden ingevoerd, bijgewerkt of verwijderd. Desnoods koppel je het aan een jaar- en maandnummer zodat je altijd de data van de afgelopen 3 maanden (ik zeg maar wat) kunt gebruiken.

De integriteit zul je op applicatieniveau waterdicht moeten timmeren (risico: klein foutje kan de boel in de soep laten draaien) en normalisatieliefhebbers zullen hier hoofdpijn van krijgen, maar bij veel bezoek werkt deze manier van aanpak wel een stuk sneller.

/edit - veel "websitetellers" werken ook op deze manier. Real-time alle logfiles analyseren zo ook daar het beste zijn maar is qua performance simpelweg niet haalbaar. Vandaar dat veelvuldig wordt gewerkt met cumulatieve data.

[ Voor 7% gewijzigd door Anders op 16-10-2006 10:01 ]

Ik spoor veilig of ik spoor niet.


  • B-Man
  • Registratie: Februari 2000
  • Niet online
Ik zou net als 'Anders' ook de relaties tussen voorkeuren opslaan. M.a.w.: als je een voorkeur toevoegt, sla ik voor alle andere voorkeuren die ik al had op dat de relatie tussen al deze andere voorkeuren +1 is.

Hiermee kun je vervolgens een lijstje opvragen van alle voorkeuren die de user nog niet heeft, maar die anderen wel gekozen hebben, en deze ordenen op het aantal 'hits'.
Pagina: 1