Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Sugerowanie
Forum PHP.pl > Forum > PHP
piernik
potrzebuję stworzyć jakiś mechanizm wyszukiwania podobnych fraz
Mam bazę z powiedzmy 30 tys różnych fraz.
Wpisuję jakąś fraze w pole input np naprawa samochodów i system powinien wyszukać w tych frazach podobne frazy z tym że najbardziej podobne będą na samym początku czyli wynik mógłby wyglądać np tak:

samochodowa naprawa
naprawy samochodów
naprawa samochodowa
naprawa aut
remont samochodów
itd

Jak takie coś zrobić? smile.gif
na razie mam tak:
ucinam z frazy szukanej końcówki i dzielę na wyrazy i szukam w bazie 'słowo%'

Później przelatuję przez wszystkie wyniki i sortuję w php na takiej zasadzie:
dzielę frazę szukana i znalezioną na słowa i przelatuję przez wszystkie kombinacje levensteinem - wyniki sumuję i fraza z najniższym wynikiem levensteina trafia na początek.

Nie sprawdza się to przy powyżej 3 wyrazach.
Jak usprawnić takie sortowanie?
Landon
Pomysłem na pewno będzie

  1. <?php
  2. function podobne($slowo) {
  3. $licz = ($licz) ? $licz : strlen($slowo);
  4. if ($licz > 2 && substr($slowo,0,7) != "http://" && substr($slowo,0,4) != "www.") {
  5. $shortest = -1;
  6. $query = mysql_query("SELECT * FROM {{table}}", "keywords");
  7. while($row = mysql_fetch_array($query)) {
  8. $lev = levenshtein($slowo, $row['name']);
  9. if ($lev == 0) {
  10. $closest = $row['name'];
  11. $shortest = 0;
  12. break;
  13. }
  14. if ($lev <= $shortest || $shortest < 0) {
  15. $closest = $row['name'];
  16. $shortest = $lev;
  17. }
  18. }
  19. $return = ($shortest != 0) ? 'Czy chodziło Ci o: <a href="?q='.$closest.'">'.$closest.'</a>' : '';
  20. }
  21. return $return.'<br>';
  22. }
  23. ?>


Jeżeli słowo nie ma więcej niż 2 litery porównuje je z istniejącymi w bazie.. Mam to w wyszukiwarce ale sa błędy np jak mam w bazie Google a wpisze google to proponuje porównać... A moim zdaniem powinno taki przypadek olać tongue.gif

Edit:

Dobra rozwiązanie teraz porównuje

  1. <?php
  2. function podobne($slowo) {
  3. $licz = ($licz) ? $licz : strlen($slowo);
  4. if ($licz > 2 && substr($slowo,0,7) != "http://" && substr($slowo,0,4) != "www.") {
  5. $shortest = -1;
  6. $query = mysql_query("SELECT * FROM {{table}}", "keywords");
  7. while($row = mysql_fetch_array($query)) {
  8. $lev = levenshtein($slowo, $row['name']);
  9. if ($lev == 0) {
  10. $closest = $row['name'];
  11. $shortest = 0;
  12. break;
  13. }
  14. if ($lev <= $shortest || $shortest < 0) {
  15. $closest = $row['name'];
  16. $shortest = $lev;
  17. }
  18. }
  19. if (strtoupper(slowo) != strtoupper($closest)) 
  20. $return = ($shortest != 0) ? 'Czy chodziło Ci o: <a href="?q='.$closest.'">'.$closest.'</a>' : '';
  21. }
  22. return $return.'<br>';
  23. }
  24. ?>


Umie ktoś lepiej to rozwiązać?

Trochę jest tu:
http://pl.php.net/levenshtein
http://pl.php.net/similar-text
merk
Być może to będzie pomocne:
http://dev.mysql.com/doc/refman/5.0/en/ful...l-language.html
guitarnet.pl
po pierwsze 30 tys wpisow i takie sugestie to nie jest dobry pomysl... szczerze mowiac fatalny, wyobrazcie sobie obciazenie serwera mysql takimi zapytaniami

co ja zrobilem to cachowanie w sesji wpisanego wzoru szukania czyli jak ktos wpisze w jednej sesji jakis wyraz zostanie on zapamietany i przywolany przy powtorzneiu, dodatkowo wyniki wyszukiwania i wpisany wzor zapamietywane sa w osobnej tabeli ktora jest przeszukiwana w pierwszej kolejnosci

oczywiscie nalezy oszacowac czy taka tabela ma sens pod katem wystepowania powtorzen, w moim przypadku mam duzo wiec ma sens wysylac dodatkowe szybkie zapytania zamiast szukac w duzej bazie

spotkalem sie rowniez z rozwiazaniem opartym na dodatkowej specjalnie generowanej tabeli z indeksami z 2 polami keyword-wyniki ktora jest przeszukiwana zamiast prawidlowej z 30tys , taka skrotowa tabela
nalezaloby oczywiscie sprawdzic czy i jesli wystepuje oszczednosc operacji i czasu odwolania, w tej tabeli odswizanej np co 24 godz znajduja sie, nigdy nie mialem czasu tego wdrozyc ale na oko widac ze w moim systemie to lepsze i szybsze rozwiazanie niz cache na sesjach i podwojne sprawdzanie cachu
Landon
wydaje mi sie że to powinno się przydać, no ale ma podobno problemy z pl znakami...

http://dev.mysql.com/doc/refman/5.0/en/str...unction_soundex

  1. <?php
  2. function podobne($slowo) {
  3. $licz = ($licz) ? $licz : strlen($slowo);
  4. if ($licz > 2 && substr($slowo,0,7) != "http://" && substr($slowo,0,4) != "www.") {
  5. $shortest = -1;
  6. $query = mysql_query("SELECT * FROM keywords WHERE SOUNDEX(UPPER('".$slowo."')) = SOUNDEX(UPPER(name)) ");
  7. while($row = mysql_fetch_array($query)) {
  8. $lev = levenshtein($slowo, $row['name']);
  9. if ($lev == 0) {
  10. $closest = $row['name'];
  11. $shortest = 0;
  12. break;
  13. }
  14. if ($lev <= $shortest || $shortest < 0) {
  15. $closest = $row['name'];
  16. $shortest = $lev;
  17. }
  18. }
  19. if (strtoupper(slowo) != strtoupper($closest)) 
  20. $return = ($shortest != 0) ? 'Czy chodziło Ci o: <a href="?q='.$closest.'">'.$closest.'</a>' : '';
  21. }
  22. return $return.'<br>';
  23. }
  24. ?>


tylko baza musi być w utf8_polish_ci wtedy niema problemów smile.gif

No ale np nie wyświetla dla sciana nie wyświetli ściana trzeba samemu to dopisać smile.gif
czyli REPLACE('cos w co', 'co', 'naco')

3
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.