[PHP/MySQL] Zoekresultaten sorteren op relevantie

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Voor een webapplicatie loop ik tegen het volgende probleem aan:

Ik heb een tabel met produktgegevens (merk, type, lengte, prijs, etc). Het is de bedoeling dat door het aangeven van een aantal criteria de produkten geselecteerd worden.

In eerste instantie werd de query ongeveer als de volgende pseudocode:
code:
1
2
3
4
5
6
7
SELECT  *
FROM
  tabel
WHERE ...
  AND lengte < max_lengte
  AND lengte > min_lengte
  AND ...

dus het is een opeenvolging van voorwaarden waaraan voldaan moet worden.

Stel dat iemand veel criteria opgeeft, dan zou het kunnen dat er geen produkten aan zijn wensen voldoen. Om de klant toch wat te laten zien wil ik een lijst weergeven met produkten die niet helemaal voldoen aan de criteria. Je kunt denken aan een prijs die iets hoger is, of afmetingen die net iets anders zijn. Dit wil ik dan graag sorteren op relevantie, dus in hoeverre het produkt voldoet aan de opgegeven criteria.

Een oplossing die ik heb bedacht is om per criterium de records te selecteren die hieraan voldoen. Deze krijgen een bepaald aantal punten. De records die bijna voldoen aan het criterium krijgen minder punten (eventueel afhankelijk van de afwijking). Na het uitvoeren van een aantal queries heb ik dan een grote array met punten. Deze kan ik dan optellen, sorteren en weergeven.

Nu heb ik het idee dat dit een vrij inefficiënt proces is, en dat het misschien efficiënter kan. Kunnen jullie mij een duw in de goede (of een goede) richting geven, of zit ik nu op het juiste pad?

In een later stadium zal de produktentabel bestaan uit 10.000 tot 20.000 artikelen.

[ Voor 1% gewijzigd door Verwijderd op 19-09-2003 20:40 . Reden: Layout werd verknald door lange query... ]


Acties:
  • 0 Henk 'm!

  • dip
  • Registratie: September 2003
  • Laatst online: 16-01-2023

dip

shut up ulé

Ja wat je wil is allemaal wel mogelijk.
maareh als je 10.000 tot 20.000 artikelen in je database hebt staan... zorg dan voor een dual 3.2 ghz :P

Het is wel erg lastig en complex. Want hoe wil jij aangeven wanneer een product qua afmeting zoals je aangeeft een bepaald aantal punten *verdient*.
Vervolgens is het ook nog van belang je aangeeft welke aspecten de meeste invloed hebben op de sortering.

Ik bedoel dus:
als je punten verdeelt tussen 0 en 5
dat als de lengte van een product 4 is
en de kosten 3, dat de kosten zwaarder tellen.
Je moet dus zegmaar aangeven wat het gewicht is per attribuut met een bepaalde score.

Tis behoorlijk ingewikkeld. Succes ermee. Als ik er tijd aan zou besteden zou ik dit systeem wel voor elkaar krijgen. maar ik kan zo 1,2,3 niet echt zeggen hoe je t beste kan beginne :x

[ Voor 14% gewijzigd door dip op 19-09-2003 21:51 ]

It's scientifically known, that base improves the tase of cheezes!


Acties:
  • 0 Henk 'm!

  • simon
  • Registratie: Maart 2002
  • Laatst online: 11:40
Misschien moet je het dan niet met een query doen, maar met een 'echt' zoek systeem, zoals de zoeck van GoT met de Omega engine werkt. Dat scheelt je weer wat in processor stress :)

|>


Verwijderd

Topicstarter
Het is inderdaad de bedoeling om ook nog met wegingsfactoren te werken, zoals dip zegt. Een artikel krijgt punten aan de hand van de afwijking met het criterium, bijv:
Criterium: Prijs < 1000
Prijs: 1000 -> 5 punten
Prijs: 1050 -> 4 punten
Prijs: 1100 -> 3 punten
Prijs: 1150 -> 2 punten
Prijs: 1200 -> 1 punt
Prijs > 1200 -> geen punten

De prijs weegt dan bijvoorbeeld zwaarder dan de afmetingen, zodat je voor de afmetingen bijvoorbeeld maximaal 3 punten kun scoren.

En misschien heb ik dan die dual 3,2 GHz wel nodig, maar die heb ik gewoon niet :)

  • simon
  • Registratie: Maart 2002
  • Laatst online: 11:40
Als je die snelheid kracht niet hebt, lijkt het me niet verstandig om iets te creëren wat het nodig heeft. Je kan ook een 'engine' gebruiken, die gebruik maakt van een aparte 'index'... Die dus op een bepaald moment indexeert, ipv real-time zoeken.. Kan veel effectiever zijn, en zou je nog wel eens die dual 3.2 GHz kunnen schelen..

|>


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Dus je bedoelt dat de zoekqueries eerst uitgevoerd worden, gecached worden en als de gebruiker ze nodig heeft getoond worden?

In dat geval zou ik elke dag alle mogelijke queries moeten gaan afvuren en de resultaten daarvan opslaan. Dan heb je oneindig veel mogelijkheden, dus ook oneindig veel verschillende queries die uitgevoerd en opgeslagen moeten worden. Ik vraag me daarom af of ik de post van Simon goed begrepen heb, of dat de index toch anders in elkaar zit :)

Acties:
  • 0 Henk 'm!

Verwijderd

Laat eerst een query uitvoeren die de maximaal tolereerdbare verschillen opvraagt.. bijvoorbeeld gevraagd wordt een prijs van 120 -> zoek tussen 100 en 140..
resultset is dan al aardig beperkt..

deze resultaten of queries kunnen uiteraard gecached worden.
Vervolgens kun je per onderdeel (dus voor EN prijs EN afmeting etc) op relevantie een aantal punten geven.
exact gelijk = 10 punten, afwijkend is 5 en lager.

Als je uiteindelijk 1 eindscore wil hebben kun je alle punten optellen en kijken wat het hoogste is.

Mocht je prijs belangrijker vinden kun je uiteraard een waarderingssysteem toevoegen:
bijvoorbeeld:
prijswaardering = 10
afmetingwaardering = 8
..
en dan tel je de punten zo op:
score = prijswaardering * prijspunten + afmetingwaardering * afmetingpunten + ... * ... + ...

Dit alles kan eenvoudig in een filtertje worden gestopt direct nadat je de resultaten binnen hebt. Kost wel wat processorkracht, maar vanwege de berperkte resultset (je beoordeeld mers niet op alle producten maar enkel binnen een bepaalde range) is het voor een totale database van 10 a 20 duizend denk ik zeker te doen.
Mits je niet TEveel bezoekers hebt, maar dan moet je de range wat verder beperken of ook een cache systeem inschakelen op de eindresultaten

Acties:
  • 0 Henk 'm!

Verwijderd

een cachesysteem bouwt zichzelf op
Het onthoudt de laatste x aantal queries, gegevens of eindresultaten.

Stel dat je een cache systeem op de gegevens wilt bouwen:

- je stelt dan in hoeveel gegevens je wilt onthouden in een stuk geheugen.
- Iedere query sla je op, in dit geval sla je de gegevens op, maar je kunt een cache zetten in meerder fases. Dit moet je zelf op efficientie beoordelen.
- Als je boven de maximale hoeveelheid te onthouden gegevens komt dan vervang je de oudste, zo laat je nooit het systeem overlopen.
- bij elke volgende query kijk je eerst even in de cache of er nog bruikbare gegevens staan
- zorg ook voor een controlemechanisme zodat eventuele vernieuwingen in de gegevens ervoor zorgen dat OF de cache meeveranderd, of de cache leeg raakt.
- staan er bruikbare, niet verouderde gegevens in, dan gebruik je deze. Zo zorg je ervoor dat niet de hele query weer op de database losgelaten hoeft te worden..

Zelf moet je nog bepalen hoeveel je in de cache opslaat en waar de cache wordt geplaatst: wil je alle querieresultaten opslaan (veel geheugen nodig) of de eindresultaten (minder waarschijnlijk dat iemand exact hetzelfde opvraagdt)

Afhankelijk van de waarschijnlijkheid dat dezelfde gegevens gevraagd en mate van processorontlasting moet je dit bepalen.
Je kunt uiteraard meerdere caches gebruiken, maar teveel cache levert ook weer vertraging op. Kwestie van testen en redeneren.

[ Voor 14% gewijzigd door Verwijderd op 21-09-2003 16:55 ]


Acties:
  • 0 Henk 'm!

  • simon
  • Registratie: Maart 2002
  • Laatst online: 11:40
Verwijderd schreef op 21 September 2003 @ 14:52:
Dus je bedoelt dat de zoekqueries eerst uitgevoerd worden, gecached worden en als de gebruiker ze nodig heeft getoond worden?

In dat geval zou ik elke dag alle mogelijke queries moeten gaan afvuren en de resultaten daarvan opslaan. Dan heb je oneindig veel mogelijkheden, dus ook oneindig veel verschillende queries die uitgevoerd en opgeslagen moeten worden. Ik vraag me daarom af of ik de post van Simon goed begrepen heb, of dat de index toch anders in elkaar zit :)
Ik geloof dat bijvoorbeeld bij GoT elk 'bericht' apart geindexeerd wordt, door een bepaalde search engine die niet 'bijvoorbeeld' mysql gebruikt.. En zo is dat prestatie 'zuiniger' :)

|>

Pagina: 1