Full Text search in forum

Pagina: 1
Acties:

  • bartvb
  • Registratie: Oktober 1999
  • Laatst online: 15-09 12:33
Ben met een groep mensen bezig met het schrijven van een forum dat zo'n beetje op het nivo van vB e.d. zit (en daarboven ofcourse ;)).

Eigenlijk alle features die we er voor deze versie in willen hebben zijn geimplementeerd waar we nu vooral nog mee zitten is de search.

Forum is geschreven in PHP en draait op MySQL, MS SQL, PostgreSQL, Oracle en via ODBC. Om die reden valt de standaard MySQL fulltext zooi af. Ook omdat die in de 3.x versie van MySQL zacht gezegd nogal brak is (geen partiele woorden, geen booleans, bijna niet te tweaken behalve via compile, zelfs voor stopwords).

We gaan dus denk ik maar zelf iets bouwen. Zitten op dit moment te denken aan het volgende:

table words:
wordid | word | wordcount

table searchindex
wordid | postid | intitle

Lijkt me redelijk voor zich spreken.
Wordcount geeft aan hoe vaak het woord voorkomt en kunnen we dus gebruiken om stopwords te herkennen (als het in meer dan x keer voorkomt is het een stopword). Verder kan die wordcount IMO gebruikt worden voor relevantie. Woorden met een lage wordcount zijn 'belangrijker'.

Intitle geeft aan of het woord in de titel van een bericht voorkomt (duh).

Vraag is of er hier nog mensen zijn die hier nog slimme ideeen over hebben, verbeteringen, te verwachten problemen, uitbreidingen..

Oh, en heeft er iemand toevallig leuke URL's liggen over het maken van fulltext searches in databases? Heb redelijk wat zitten zoeken maar weinig kunnen vinden :(

Alvast ontzettend bedankt!

Verwijderd

hier misschien? (BM)

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

tsja, ik denk dat het geen onhandige oplossing is, of het de beste is of niet weet ik niet ;)

misschien nog een tabel 'ruiswoorden' die dan zowiezo niet in de lijst opgenomen worden (woorden als de/het/een/dan/dat/dit/etc/bla enzovoort)

en denk er ook over een handige manier om het te indexeren (split op ' ' en dat allemaal maar de DB in :?) na.

  • Basszje
  • Registratie: Augustus 2000
  • Laatst online: 15-09 11:04

Basszje

Reisvaap!]

Misschien niet zo handig om die word count te doen, kan nl redunante gegevens opleveren.

Mijn indexer ziet er iig zo uit

keyword
id - keyword

keyword_document
kw_id - doc_id

document
doc_id doc_path etc etc

Kan je gewoo een count doen op die middel tabel en je krijg dan ook in je keyword tabel elk keyword maar 1x ( wat het zoeken bevorderd ) :)

Succes.

Beware of listening to the imposter; you are undone if you once forget that the fruits of the earth belong to us all, and the earth itself to nobody.


  • bartvb
  • Registratie: Oktober 1999
  • Laatst online: 15-09 12:33
Sjako, die had ik gevonden maar staat niet echt veel bruikbaars in ;)

ACM goed plan! Stop/ruiswoorden tabel klinkt goed..

Indexeren ben ik nog niet echt mee bezig geweest.. In iedergeval HTML strippen dan splitten op alles dat geen letter of cijfer is ofzo. Maar moet allemaal liefst wel een beetje snel gebeuren. Bij het converteren van een forumdatabase van 1M posts ofzo wil je geen halve dag zitten wachten tot PHP eens uit ge-regexpt is..

Bas; Is waar.. Count op een table met 2 INT's zou behoorlijk snel moeten zijn. Misschien tijdens het importeren om de 2000 posts een group by op die table doen en dan alle ruiswoorden zoeken (alles dat te vaak voor komt) en dat naar de ruiswoorden tabel moven..

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op donderdag 27 september 2001 13:51 schreef bartvb het volgende:
Sjako, die had ik gevonden maar staat niet echt veel bruikbaars in ;)
Indexeren ben ik nog niet echt mee bezig geweest.. In iedergeval HTML strippen dan splitten op alles dat geen letter of cijfer is ofzo. Maar moet allemaal liefst wel een beetje snel gebeuren. Bij het converteren van een forumdatabase van 1M posts ofzo wil je geen halve dag zitten wachten tot PHP eens uit ge-regexpt is..
Als je een preg_split oid doet, kan je natuurlijk op \b (word delimiter, woord begin) splitten oid

Verwijderd

Ik heb het ongeveer hetzelfde inelkaar gezet als jij nu voorstelt. Maar met een paar verschillen. Ik heb ook 2 tabellen:

words:
id(int) - word(varchar(20))

searchindex:
topic(int) - wordid(int) - hits(int)

hits representeerd het aantal hits van wordid in die topic (die kun je later summen en dan daar op sorteren voor een erg precies resultaat).

In ieder geval moet je die ruiswoorden er uit gooien, maar verder laat ik ook woorden met minder dan 3 letters niet indexeren (wordt hier op GoT volgens mij ook niet gedaan).

En verder, tja het is goed nadenken, maar er moet uit te komen zijn (het is mij wel gelukt iig).

  • bartvb
  • Registratie: Oktober 1999
  • Laatst online: 15-09 12:33
Denk dat ik woorden met 2 tekens ook indexeer, erg handig voor afkortingen (PHP, SQL, dat soort zooi).
Belangrijkste reden dat ze die 3 letter dingen weglaten is dat een hoop stopwoorden daar binnen vallen (de, het, een, is, the, a, in, etc). Maar als je op een wat slimmere manier die stopwoorden zoekt dan kan je ook 3 letter dingen indexeren..

preg_split is inderdaad wel een strak plan :)

Verwijderd

Op donderdag 27 september 2001 14:05 schreef bartvb het volgende:
Denk dat ik woorden met 2 tekens ook indexeer, erg handig voor afkortingen (PHP, SQL, dat soort zooi).
Belangrijkste reden dat ze die 3 letter dingen weglaten is dat een hoop stopwoorden daar binnen vallen (de, het, een, is, the, a, in, etc). Maar als je op een wat slimmere manier die stopwoorden zoekt dan kan je ook 3 letter dingen indexeren..
Is idd waar, es over nadenken. Trouwens m'n vorige post is wat aangepast (had niet goed gelezen)

  • tomato
  • Registratie: November 1999
  • Niet online
Op donderdag 27 september 2001 13:55 schreef ACM het volgende:
Als je een preg_split oid doet, kan je natuurlijk op \b (word delimiter, woord begin) splitten oid
In niet-POSIX regex engines is een 'woord-teken' niets anders dan [-_a-zA-Z0-9], maar is je regex POSIX complient dan kunnen locales ook een rol gaan spelen (in het duits zou nu ook een eszet eronder vallen). Erg makkelijk, maar weet wel even wat je precies moet verwachten en heilig is een 'word boundary' niet, dat is in dat geval de locale support. In sommige tools gebruik je trouwens \< en \> als word boundaries (\b matcht beiden, begin of eind van een woord).
Waarom eigenlijk preg_split? Match gewoon op een pattern dat een woord omschrijft...
Letten op HTML en niet-HTML wordt trouwens wel erg lastig, want bijvoorbeeld binnen code-tags wil je het waarschijnlijk weer wel meenemen. Als je echt ver wilt gaan bouw je het indexeren in in je UBB parser, scheelt je een hoop werk ;)

Waarom trouwens die wordcount in je tabel words? Voor stopwoorden zijn betere manieren te verzinnen en het lijkt me logischer om een wordcount op te nemen in je tabel searchindex.

Verder denk ik dat dit soort methoden zeker wel nuttig zijn, maar je blijft met het probleem zitten dat zoeken op "ontzettend bedankt" (dus met de quotes) niet zomaar gaat. Je kunt hier wel oplossingen voor verzinnen met deze db structuur, maar efficient zal het zeker niet worden. Terwijl dergelijke zoekopdrachten soms toch wel erg belangrijk zijn.

[edit]
Wbt die word boundaries, denk eraan dat de meeste engines iets als N.A.S.A niet als woord zullen zien...
Ik denk trouwens dat een /w nuttiger zal zijn dan een /b, maar daar gelden dezelfde puntjes voor als die ik al noemde.
Ik heb het even nagekeken, perl regexen zijn niet POSIX complient (zoals zovelen), maar proberen wel locale support te bieden. Dit lukt maar ten dele, in \w bijvoorbeeld wordt van de systeem locales gebruik gemaakt, maar in character class ranges ([a-z] bijvoorbeeld) niet. Weer andere tools bieden uit zichzelf geen locale support, maar stiekem wel omdat de tool bijvoorbeeld gecompileerd op een systeem met een POSIX complient C library (maar dan nog geldt dit vaak maar ten dele, afhankelijk van wanneer de schrijver gebruik maakt van C library functies).

/end of lesson ;)

  • bartvb
  • Registratie: Oktober 1999
  • Laatst online: 15-09 12:33
Hmm, goeie :) Locale had ik eerlijkgezegd nog niet aan gedacht.. Verder ook eens goed in de gaten houden hoe dit werkt bij Big-5 en dat soort meuk. Grmbl..

Misschien alles omdraaien en alleen splitten op dingen die we als word boundary willen zien? Dus ' .,;:"-+' etc? Heb zo'n vaag vermoeden dat het daar niet echt sneller op wordt. Maar goed, dat snel is niet zo super van belang aangezien de conversie van de hele database als het goed is maar 1x hoeft te gebeuren.

Phrase searching is inderdaad een probleem met deze methode, nog niet echt een geweldige oplossing voor kunnen bedenken..

Iets waar ik wel aan het zitten denken is het opslaan van de locatie van een woord (b.v. het x-te woord, of op 20% van de text). Misschien dat dat ook iets is dat relevantie aangeeft (is iets waar Chem mee kwam in een eerder thread over fulltext search).

Als je opslaat welk woord het is in een text zou je evt wel phrase searching kunnen doen hoewel dat weer erg heftig wordt voor je database... Gok ik.

Of je doet eerst een simpele AND met je woorden uit je phrase en doet dan nog een LIKE '%ontzettend bedankt%' op de resultaten die je terug krijgt.. Gok dat dat nog wel het eenvoudigs is. Alleen opletten dat je dat niet gaat doen op 10.000 rows ofzo ;(

Toch nog maar eens wat meer gaan Google-en ;)

Maar in iedergeval erg bedankt voor de hints, zijn al een hoop bruikbare dingen uit gekomen!

Meer hints, tips en aanbevelingen zijn meer dan welkom..

  • tomato
  • Registratie: November 1999
  • Niet online
Op donderdag 27 september 2001 15:33 schreef bartvb het volgende:
Als je opslaat welk woord het is in een text zou je evt wel phrase searching kunnen doen hoewel dat weer erg heftig wordt voor je database... Gok ik.
Dat is wel een originele oplossing, daar had ik zelf nog niet aan gedacht. Of het voor veel overhead zorgt? Denk dat het wel meevalt.
Of je doet eerst een simpele AND met je woorden uit je phrase en doet dan nog een LIKE '%ontzettend bedankt%' op de resultaten die je terug krijgt.. Gok dat dat nog wel het eenvoudigs is. Alleen opletten dat je dat niet gaat doen op 10.000 rows ofzo ;(
Dat kan natuurlijk altijd, maar is niet echt efficient (en gaat een beetje voorbij aan het idee van je search). Daarnaast werkt dat (evenals het opslaan van de locatie van een woord) nog steeds niet voor iets als "MacOS X" of wil je 'woorden' van 1 karakter ook op gaan slaan :?

  • bartvb
  • Registratie: Oktober 1999
  • Laatst online: 15-09 12:33
BTW die Locale tip was een goeie ;) Nu ff uit aan het zoeken of ik het voor elkaar krijg Chinese (Big-5 etc) tekst op woorden te splitten ;)

Maar indeed, iets als 'MacOS X' werkt dan niet maar ja het blijft een hobby oplossing dus 't zal niet perfect worden ben ik bang.. 'MacOS X' werkt weer wel als je die LIKE gaat gebruiken maar ja, da's dus niet echt netjes c.q. efficient.

Trouwens net eens zitten zoeken maar kan maar weinig nuttigs over dit soort spul vinden :( Vooral omdat je constant de standaard fulltext indices van MySQL en PostgreSQL e.d. tegen komt :( Irri...

Toch stiekum wel benieuwd hoe iets als Google dit doet, geloof alleen niet dat daar een RDBMS achter zit :)

Verwijderd

als je op een "exact phrase" zoekt, en je maakt gebruik van die index table, hoef je toch niet nog een like uit te voeren op de textTabel ?

ipc zou je alleen maar hoeven te kijken of het woord in de eerst volgende rij met hetzelfde doc_id gelijk is aan het 2e (Xe) woord uit de "exact phrase"

of helpt dat niet ? :)

interessant dit!

  • bartvb
  • Registratie: Oktober 1999
  • Laatst online: 15-09 12:33
Snow: verrek ja ;) Heb je gelijk in..
Maar hoe doe je dat in een SQL query dan? Zonder subselects... ;(

BTW net ff wat zitten chatten met een taiwanees en dat Big-5 ga ik maar buiten beschouwing laten :) Ze hebben geen normale word boundaries schijnbaar :(

Nu ff aan het zoeken op www.tue.nl/bib/ denk dat ik maar eens een boek ga lezen over dit spul ofzo..

  • bartvb
  • Registratie: Oktober 1999
  • Laatst online: 15-09 12:33
Naar www.tue.nl/bib/ geweest en daar 'Indexing Techniques for advanced database systems' gehaald :)
Staat een redelijk stuk in over 'inverted files' en meer van dat soort spul. Lijkt interessant, nu nog tijd vinden het te lezen, zal dit weekend niet veel worden :(
Verder ook 'Managing Gigabytes, compressing and indexing Documents and Images' geleend, kan ook interessant zijn..

Als ik wat vind laat ik nog van me horen :)
Oh, als er nog iemand boektips heeft houd ik me aanbevolen :D

Verwijderd

Op donderdag 27 september 2001 23:12 schreef bartvb het volgende:
Maar indeed, iets als 'MacOS X' werkt dan niet maar ja het blijft een hobby oplossing dus 't zal niet perfect worden ben ik bang.. 'MacOS X' werkt weer wel als je die LIKE gaat gebruiken maar ja, da's dus niet echt netjes c.q. efficient.
Dat heb ik hier opgelost door VOOR het doorzoeken van de echte data, een Linkwords tabel te zoeken op een WHERE Name LIKE '%$query%'. In die tabel staan een hoop linkwords (cfr. sponsored words) van dingen waar veel op gezocht wordt en die ik dan dus direct kan presenteren.

Die tabel is vele malen kleiner dan de index die automatisch gemaakt wordt door je indexer, dus dat zoeken met LIKE valt heel goed mee.

  • Nielsz
  • Registratie: Maart 2001
  • Niet online
oud topic, dat weet je? ;)

Verwijderd

Op dinsdag 27 november 2001 16:47 schreef Nielsz het volgende:
oud topic, dat weet je? ;)
Altijd handig voor een search :)

  • TangLeFuzZ
  • Registratie: Juni 2001
  • Laatst online: 23-08 15:45
Hey,

ik heb het bovenstaande ook al een hele tijd, maar ik heb nog geen 'hits' in m'n searchtabel staan, dus het aantal keer dat een woord in een topic voorkomt is bij mij nog onbekend.

Ik wil ook graag ordenen op beste result, dus ik ga dat hits veld er wel in bouwen, MAAR: ik heb in m'n search tabel geen koppeling gemaakt tussen topicid en wordid, maar postid en wordid.
Een woord kan dan in een posting wel x keer voor komen, maar misschien bestaat een andere topic wel uit meer postings met iets minder 'hits' dan die x, terwijl dat woord dus toch vaker voor komt in die topic!

Wat zouden jullie in dit geval doen, de hits die je terugkrijgt van alle postings met hetzelfde topicid optellen, en dan nog 's ordenen, OF de searchtabel ombouwen naar een wordid/topicid/hits ?
Dat laatst wordt wel erg lastig, ik heb al ERG veel items in die tabel staan...

edit: hmm, misschien kan ik ook wel 's met een count(search.wordid) AS score gaan werken...
Pagina: 1