Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Opis jak zrobić wyszukiwarkę z wyświetlaniem trafności
Forum PHP.pl > Forum > PHP
spenalzo
Ponieważ zaciekawiło mnie to co napisał Dragossani w <b>tym</b>wątku, postudiowałem manual do MySQLa i oto co z tego wynikło - wyszukiwarkę z określaniem trafności można zrobić jednym zapytaniem :-)

<i><b>Jak zrobić wyszukiwarkę?</b></i>

Zacznijmy od początku:
zakładamy, że chcemy zrobić własną wyszukiwarkę do forum phpBB.
Na początku dodajemy do istniejącej tabeli prefix_posts_text jedno pole:
  1. ALTER TABLE prefix_posts_text ADD FULLTEXT (post_subject,post_text)

Jeżeli wszystko przebiegło pomyslne to możemy zająć się stworzeniem zapytania formularza wyszukiwania.
Do wyszukiwania używamy funkcji mysqla
  1. MATCH(col1,col2,..) AGAINST ('szukany_tekst')

która zwraca wyniki trafności wyszukiwania.

Teraz zróbmy z tego zapytanie:
  1. <?php
  2. $q=mysql_query(&#092;"SELECT MATCH(post_subject,post_text) AGAINST ('\".$_POST[\"f\"].\"') AS stopien, post_text, post_ID,post_subject FROM prefix_posts_text ORDER B
    Y
  3. stopien DESC&#092;") or die(mysql_error());?>

zakładając, że w zmiennej $_POST["f"] mamy szukane wyrażenie.

Jeżeli zapytanie działa, to jedziemy dalej, jeżeli nie to szukamy rozwiązania w manualu.
Teraz przypisujemy odpowiednie wartości do tablic:
  1. <?php
  2.  for($i=0; $i<mysql_num_rows($q); $i++)
  3.  {
  4. if($t[&#092;"stopien\"]>0)
  5. {
  6.  $stopnie[]=$t[&#092;"stopien\"];
  7.  $IDs[]=$t[&#092;"post_ID\"];
  8.  $sub[]=$t[&#092;"post_subject\"];
  9.  $post[]=$t[&#092;"post_text\"];
  10. }
  11.  }
  12. ?>


Teraz przygotujmy wyświetlanie wyników.
Ponieważ zwracane wyniki trafności nie są za każdym razem identyczne, wyszukujemy najwiekszą wartość:
  1. <?php
  2.  $max=$stopnie[@array_search(@max($stopnie),$stopnie)];
  3. ?>


Teraz (w pętli) z proporcji obliczamy procenty trafności każdego zapytania, i wyświetlamy dane:
  1. <?php
  2. for($i=0; $i<count($stopnie); $i++)
  3. {
  4.  $proc=floor(($stopnie[$i]*100)/$max);
  5.  // instrukcje wyświetlające
  6. }
  7. ?>


I wyszukiwarka gotowa :-)
:arrow: <b>Przykład</b>
Powyżej można zobaczyć przykład działania wyszukiwarki podpiętej pod phpBB.

<i><b>Metoda działania wyszukiwarki.</b></i>
(na podstawie moich obserwacji)
Trafność zostaje wyliczona w następujący sposób - jest liczona ilosc szukanych słów i podstawiona do ilości ogólnej wyrazów w ciągu i na podstawie tego zostaje zwrócona wartość. Czyli mówiąc prościej - na górze strony wyszukiwania (największa trafność) będą posty z najwyższym stosunkiem wyrazów do szukanego ciągu, czyli np. najkrótsze posty z największą ilością szukanych słów.
Ograniczeniem jest długość ciągu - wyszukiwarka działa dopiero przy szukanych wyrażeniach dłuższych niż 3 znaki.
Wankster
WOW! Dzięki spenalzo! Dzięki bardzo!
Marusz
Haha, najbardziej podobał mi się pierwszy post po wpisaniu słowa szukanego: admin smile.gif To tylko taki mały offtopic winksmiley.jpg
wojto
spenalzo dzieki za ta wyszukiwarke, kiedys probowalem zrobic taka.
mam jeszcze pytanie i prosbe, czy dalo by sie tak zrobic (moze juz to jest na tamtej wyszukiwarce), aby zaznaczalo szukany tekst w wynikach, ale chodzi mi o to by sie linki nie psuly.
problem szerzej przedstawilem tutaj
spenalzo
Cytat
Haha, najbardziej podobał mi się pierwszy post po wpisaniu słowa szukanego: admin smile.gif To tylko taki mały offtopic winksmiley.jpg

No cóż... Przykład radosnej twórczości naszego genialnego forumowicza rdpan'a... laugh.gif
A post pokazuje sie, ponieważ został przeniesiony do ukrytego forum, a nie skasowany :-)
sivyer
Artykul "Using MySQL Full-text Searching" dostępny na stronach http://www.zend.com
Mnichasso
A można by tak dać opis wyszukiwarki szukającej w plikach ? I żeby była oparta ta wyszukiwarka na plikach ?
spenalzo
Cytat
A można by tak dać opis wyszukiwarki szukającej w plikach ? I żeby była oparta ta wyszukiwarka na plikach ?

uuu, tutaj to nie jest takie proste :-)
W tej wyszukwarce co wyżej 99% roboty odwala mysql, a na plikach to musiałbym sam napisać algorytmy, funkcje itd. Ale może kiedyś?
Mnichasso
a dało by sie zrobić wyszukiwarke na mysql która by szukała w plikach txt które mają postać:


[list]1|http://jakiś adres|Nazwa strony|Opis strony|E-mail|1057855002
2|http://jakiś adres|nazwa strony|Opis strony|e-mail|1061981292[list]
spenalzo
Cytat
a dało by sie zrobić wyszukiwarke na mysql która by szukała w plikach txt które mają postać:

Jak pliki to nie MySQL.
Z plikami to jest taki problem, że nie da się napisać jednej wyszukiwarki dla każdego rodzaju pliku, ponieważ każdy zapisuje swoje pliki w inny sposób.
msulik
Może coś zrobiłem nie tak, ale mnie się to nie podoba :|

Po pierwsze:
Cytat
(...) na górze strony wyszukiwania (największa trafność) będą posty z najwyższym stosunkiem wyrazów do szukanego ciągu, czyli np. najkrótsze posty z największą ilością szukanych słów

Hmm... jakoś nie mogę znaleźć sensu takiego kryterium oceniania trafności. <update>Patrz niżej ten post.</update>


Po drugie, po wykonaniu "ALTER TABLE" ponad dwukrotnie wzrosła objętość tabeli (!). Dyskwalifikacja, nie wiem ile zajmuje u Was np. baza phpBB, ale wydaje mi się, że w większysch serwisach - dużo. Pole FULLTEXT staje się bowiem indeksem i kopiuje pole z tekstem każdego rekordu, a więc, jeśli rozpatrywana tabela jest główną tabelą serwisu, to praktycznie objętość bazy wzrasta dwukrotnie.


Zastanawiam się cały czas nad skuteczną wyszukiwarką, np. taką, która opiera się na osobnej tabeli słów kluczowych (relacja {id_słowa, słowo}), generowanych z dodawanych tekstów oraz na relacji {id_słowa, id_tekstu, ilość_wystąpień}. Przy obliczaniu trafności, można połączyć dwa parametry: ilość wystąpień słowa w danym tekście (obliczana jednorazowo przy dodawaniu/edycji tekstu) oraz ilość dopasowanych słów, tzn. ile spośród wpisanych w wyszukiwarce słów, znalazło się w tekście. Nie wiem tylko, jak to połączyć - może sumę "ilości wystąpień"? Albo może średnią z "ilości wystąpień" (tzn. "suma ilości wystąpień" podzielić przez liczbę słów wpisanych w wyszukiwarce)? Tekst z najwyższą średnią (lub sumą, lub innym wyliczonym parametrem) otrzymuje 100%, a następne, odpowiednio mniej. Muszę dokonać obliczeń i wtedy zastanowić się, jaki wzór opracować, może jakaś średnia arytmetyczna ważona czy cuś...

Do tego dochodzi jeszcze ta nieszczęsna odmiana rzeczowników przez przypadki...

Korzyści z fulltextu są nieocenione, ale ten wzrost objętości...

<dodatek date="2003-09-01" time="09:51">
Poza tym nie można podać własnej definicji termu (to określenie pojawia się w teoretycznych opracowaniach dotyczących tego tematu), na przykład term zawierający myślnik zostanie potraktowany jako dwa termy, z których drugi jest termem "zabronionym", czyli takim, który nie może wystąpić w dokumencie.

Poszperałem trochę w sieci i znalazłem kilka prac poświęconych tematowi "ważenia" dokumentów. Już w dokumentaji mysql'a można wyczytać, na czym polega "ważenie" termu kluczowego - im więcej dokumentów, w których ten termu występuje, tym bardziej term traci na wadze. Chodzi o to, żeby wpisując rzadko występujące termy, otrzymać dokument, który zawiera największe jego natężenie. Wzór na wagę termu w dokumencie uwzględnia ilość wystąpień termu w dokumencie ©, ilość dokumentów zawierających term (Dt) oraz ilość wszystkich dokumentów w archiwum (N) i logarytmicznie rośnie wraz ze wzrostem liczby dokumentów w archiwum oraz maleje wraz ze wzrostem liczby dokumentów zawierających term. Ufff winksmiley.jpg
waga_termu_w_dokumencie = C * log (N / Dt)
Tylko nie wiem, dlaczego we wzorze pojawia się logarytm :| Logarytm jest funkcją rosnącą wolniej niż funkcja liniowa. Przy dużych argumentach różnice wartości są niewielkie. Poszperam w sieci jeszcze o tym, może trzeba trochę pogrzebać w statystyce matematycznej angrysmiley.gif
</dodatek>
orson
witam ...

pozwolilem sobie zoptymalizowac ta funkcje ... wg moich testow oraz obserwacji [obie funkcje wywolane w 2 oknach na tej samej bazie ] dzialanie [ zwracane wyniki ] jest identyczne ...
oto poprawiony kod:
[php:1:38f3001feb]<?php
$query = "SELECT MATCH( kolumny full text ) AGAINST (".$_GET['szukane'].") AS stopien, reszta, oddzielona, przecinkami FROM nazwabazy ORDER BY stopien DESC";
$result = mysql_query ($query) or die (mysql_error());
$n=0;
while ($line = mysql_fetch_array($result, MYSQL_ASSOC)){
if($line["stopien"]>0){
$stopnie[]=$line["stopien"];
$proc=round((($stopnie[$n++]*100)/$stopnie[0]),2);
print '
wszystkie kolumny spelniajace kryteria z bazy sa wyswietlane przez $line['nazwa_kolumny']
dodatkowo w zmiennej $proc jest procentowo zawarta wartosc stopnia danego rekordu w porownaniu z rekordem maksymalnym
';
}//*
}

?>[/php:1:38f3001feb]
* gdy bawilem sie ta funkcjia [poprzednia rownierz] zauwazylem [mysql_num_rows();] ze ilosc odebranych wierszy jest wieksza niz ilosc wyswietlonych .... tu mozna wsadzic wyswietlanie rekordow w inny sposob wtedy gdy stopnien = 0 [slowo jest za popularne lub nie znalezione] ale UWAGA po wpisaniu np print " nie znaleziono" ten komunikat zostanie wyswietlony tyle razy ile line['stopien'] > 0 [ dzieki petli while]

teraz moze kilka wyjasnien ...
[php:1:38f3001feb]
$max=$stopnie[@array_search(@max($stopnie),$stopnie)];
?>[/php:1:38f3001feb]
po co questionmark.gif przecierz wyniki zapytania ukladane sa wg stopnia [od najwiekszego do najmniejszego] a maxymalna wartosc jest na pozycji 0 w tabeli stopnie ...
[php:1:38f3001feb]<?php
$proc=floor(($stopnie[$i]*100)/$max);
?>[/php:1:38f3001feb]
mozna wsadzic prosto do petli :
[php:1:38f3001feb]<?php
$proc=round((($stopnie[$n++]*100)/$stopnie[0]),2);
?>[/php:1:38f3001feb] ponaddto stosujac round dos tajemy ladniejsze wyniki np w miejsce 90 z florem mamy 91 z round
funkcja jest mniejsza ... ma mniej tabel [ odpada:
[php:1:38f3001feb]<?php
$stopnie[]=$t["stopien"];
$IDs[]=$t["post_ID"];
$sub[]=$t["post_subject"];
$post[]=$t["post_text"];
?>
[/php:1:38f3001feb]
]
i wszysko jest w 1 petli ... co o tym sadzicie questionmark.gif
wszelkie komentarze mile widziane biggrin.gif:D
cya
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.