login  Naam:   Wachtwoord: 
Registreer je!
 Forum

Search (Opgelost)

Offline Wijnand - 31/10/2014 16:30
Avatar van WijnandModerator Ik heb een website waarop ik wil zoeken op onder andere:

- woord (exact woord, dus niet als je zoekt op 'pen', dat je vind 'pennen')
- woord dat begint met iets (nu mag je bij 'pen' wel 'pennen' vinden, maar niet 'balpen')
- woord dat eindigt met iets (nu mag je bij 'pen' niet 'pennen' vinden, maar wel 'balpen')
- niet exact woord

En dit dan gegroepeerd ook mogelijk: dus bv 'de balpen*' mag ook vinden 'de balpennen' en 'de balpen' mag niet 'de balpennen' vinden.

Ik dacht dat ik dit met FULLTEXT kon doen, maar dit heeft één probleem namelijk: hij doet alleen bal*, maar niet *bal (de asterisk betekent dat hierachter willekeurige characters mogen komen).

Ik heb LIKE geprobeerd, maar dat wordt een zooitje en dan wil je ook aan kunnen geven dat het om woorden gaan, dus als je zoekt op alleen 'pen', dan moet hij alle tekst vinden waarin het losse woord 'pen' vinden en niet 'pennen' of 'balpen' of iets dergelijks.

Hoe kan ik dit goed (en snel) aanpakken?

6 antwoorden

Gesponsorde links
Offline Thomas - 31/10/2014 20:39
Avatar van Thomas Moderator
Wijnand schreef:
Hoe kan ik dit goed (en snel) aanpakken?
Kies 1 van de 2 .

Tags? maar das wellicht een verplaatsing van het probleem :]

RLIKE? maar das misschien nogal zwaar?

Indexeer-service (Lucene of equivalent)? heeft wel JAVA nodig geloof ik en heb daar verder de ballen verstand van :]

Fanta-oplossing: afhankelijk van de grootte van de tekst: sla deze in spiegelbeeld op zodat deze ook geindexeerd kunnen worden en je kunt zoeken met een (tweede) postfix wildcard? 
... WHERE ... (
(MATCH(<column>) AGAINST ('<term>*' IN BOOLEAN MODE))
OR
(MATCH(<column_reverse>) AGAINST ('<term_reverse>*') IN BOOLEAN MODE))
)
en dan op een of andere manier de relevanties optellen?

Ik denk niet dat er echt een simpele oplossing voor dit probleem is.
Offline Wijnand - 03/11/2014 10:11 (laatste wijziging 03/11/2014 11:07)
Avatar van Wijnand Moderator Ik heb iets anders gezien...

Je kunt regex gebruiken. Ik denk niet dat het super snel is, maar ik ga het nu even testen of het goed werkt.

EDIT:
Gaaf, ik heb iets gevonden waardoor je regex gebruikt, maar deze ook versnelt wordt.

Ik heb een tabel met 200.000+ records.

Als ik doe:

SELECT * FROM tabel WHERE veld LIKE '%test%'

Dan werkt dat snel, maar hij vind alles, dus ook testER of STUNTtest etc. Dat wil ik niet.

Doe ik dit:

SELECT * FROM tabel WHERE veld REGEXP '^(.*[^a-zA-Z]{1})?test(.*[^a-zA-Z]{1})?$'

Dit geeft het juiste resultaat, maar duurt in mijn geval 3 seconde om te laden en hoe groter de tabel is, hoe langer het duurt (en het kan echt ontzettend snel oplopen).

Wat de oplossing is:
Beide gebruiken:

SELECT * FROM tabel WHERE veld LIKE '%test%' AND veld REGEXP '^(.*[^a-zA-Z]{1})?test(.*[^a-zA-Z]{1})?$'

Wat deze query doet is: eerst de like uitvoeren (zorgt er in mijn geval voor dat er 500 records overblijven van de 200k+. Dan over die 500 records voert hij de REGEXP uit. Opeens kost het nog geen seconde om zoekresultaten op te halen uit de database :-).

Offline Thomas - 03/11/2014 16:20
Avatar van Thomas Moderator Hier maakt mogelijk de volgorde van je predikaten (toch) uit. Misschien zou je verwachten dat de MySQL optimizer eerst de LIKE uitvoert en dan pas de REGEXP, ongeacht of de LIKE vooraan staat of niet, maar aan de andere kant maakt MySQL mogelijk gebruik van lazy evaluation.

Lazy evaluation hield volgens mij het volgende in, als je zoiets hebt:
A AND B en A evalueert tot False, dan wordt B niet geevalueerd (False AND B levert nooit True op)
A OR B en A evalueert tot True, dan wordt B niet geevalueerd (True OR B levert altijd True op)

Dat zou verklaren waarom zo'n conditie altijd in een vaste volgorde (bijvoorbeeld van links naar rechts) wordt gelezen.

Het is (eigenlijk altijd) verstandig om wat benchmarks uit te voeren op je queries.
Offline Wijnand - 03/11/2014 16:23 (laatste wijziging 03/11/2014 16:24)
Avatar van Wijnand Moderator Wat bedoel je met benchmarks? Kun je daar is wat meer info over geven?
Offline Thomas - 03/11/2014 16:38
Avatar van Thomas Moderator Analyse van hoe efficiënt je query eigenlijk is, bijvoorbeeld met EXPLAIN.

Er bestaat zelfs een BENCHMARK() functie die ik hier tegenkwam in mijn zoektocht naar lazy evaluation in MySQL. Maar dat bericht is misschien enigszins gedateerd .
Offline Wijnand - 04/11/2014 08:40 (laatste wijziging 05/11/2014 09:30)
Avatar van Wijnand Moderator De EXPLAIN is exact hetzelfde, maar de resultaten niet.

Ik deed nu eerst LIKE en toen REGEXP: 0.3 seconden.
Ik deed toen eerst REGEXP en toen LIKE: 5.8 seconden.
Gesponsorde links
Je moet ingelogd zijn om een reactie te kunnen posten.
Actieve forumberichten
© 2002-2024 Sitemasters.be - Regels - Laadtijd: 0.18s