Wyszukiwanie rekordów podobnych łańcuchem znaków

0

Witam. Problem jest trochę zagmatwany, lecz niewątpliwie kogoś zainteresuje ;). Opiszę go więc:

  • posiadamy tabelę, która zawiera pole łańcuchowe varchar, które służy jako tytuł danego rekordu
  • nie chce systemu tagów, ale mimo to chcę umozliwić dla każdego rekordu wyszukiwanie rekorów pokrewnych (podobnych, related, nazwijcie to jak chcecie :D), a chcę to osiągnąć poprzez badanie podobieństw tytułów wg. ich poszczególnych słów

Mamy zatem rekord z tytułem wejściowym (title_in), któremu będziemy szukać rekordów pokrewnych. Dalej algorytm wygląda następująco:

  • phpem dzielę title_in na kawałki jako separator używając spacji, otrzymuję array ze słowami
  • sortuję te słowa wg. długości, od najdłuższego
  • każdemu ze słów przypisuję jego wagę wg. określonego wzoru, bazując na jego długości
  • wywołuję zapytanie:
SELECT * FROM `xxx` WHERE `title` LIKE '% slowo1 %' OR `title` LIKE '% slowo2 %' OR [...] LIMIT 0,5
// operatorów "WHERE `title` LIKE xxx" jest tyle, ile słów, są logicznie połączone OR'em
  • dostaję 5 rekordów :)
  • dalej już je sortuję wg trafności licząc sumaryczną wagę trafionych słów etc.

Cóż - z racji tego, że pisałem to późno w nocy umknął mi pewien istotny szczegół [green] - przecież ja nie pobieram z bazy najbardziej trafionych tytułów, tylko 5 pierwszych z brzegu zawierających chociaż jedno słowo - a potem wg. algorytmu je sortuję. Co jest oczywiście kompletnym bezsensem :)

Jeszcze durniejszym (ale moim! :-D) pomysłem jest pobieranie np. 100 rekordów, sortowanie i wtedy odrzucenie 95 ostatnich. Ale naprawdę było już późno w nocy! :)

Napisałem, jak to jest zrobione do tej pory. A jak chciałbym by to działało? By już na etapie zapytania do bazy wywlekł mi te pierwsze 5 najbardziej trafionych i podobnych tytułów. Bazując tylko na liście słów w tablicy. Nie wiem, czy to w ogóle możliwe [green]. Ale mam nadzieję, że ktokolwiek mnie nakieruje na dobrą ścieżkę ;)

0

Robiłem kiedyś coś takiego jako procedura na MSSQL, a więc tak, przykładowa tabela z tytułami (Tytuly):

Tytuł rekordu
----------------------------------------------------
Przykładowy Tytuł pierwszy
Przykładowy Tytuł drugi
Przykładowy Tytuł rzeci

Z tej tabeli musisz uzyskać coś takiego (np. jako tabela tymczasowa #Wyrazy):

tytul_rekordu              | wyraz
----------------------------------------------------
Przykładowy Tytuł pierwszy | Przykładowy
Przykładowy Tytuł pierwszy | Tytuł
Przykładowy Tytuł pierwszy | pierwszy
Przykładowy Tytuł drugi    | Przykładowy
Przykładowy Tytuł drugi    | Tytuł
Przykładowy Tytuł drugi    | drugi
Przykładowy Tytuł trzeci   | Przykładowy
Przykładowy Tytuł trzeci   | Tytuł
Przykładowy Tytuł trzeci   | trzeci

Czyli dla każdego tytułu musisz uzyskać wiersze z poszczególnymi wyrazami (ja robiłem to za pomocą pętli while w procedurze składowanej).

Następnie musisz mieć tabelę z szukanymi wyrazami (np. #Szukane):

wyraz
----------------------------------------------------
Przykładowy
drugi

Teraz wystarczy zapytanie:

select tytul_rekordu, count(*) as ile_wyrazow_pasuje
from #Wyrazy w inner join #Szukane s on w.wyraz = s.wyraz
group by tytul_rekordu
order by 2 desc

W ten sposób uzyskujesz wynik:

tytul_rekordu              | ile_wyrazow_pasuje
----------------------------------------------------
Przykładowy Tytuł drugi    | 2
Przykładowy Tytuł pierwszy | 1
Przykładowy Tytuł trzeci   | 1
0

Jeśli uzywasz mysql to polecam wyszukiwanie pełnotekstowe.
http://dev.mysql.com/doc/refman/5.1/en/fulltext-natural-language.html

0
  1. Full Text Search
  2. Soundex
0

Dzięki wszystkim za odpowiedź, przydało się ^^

1 użytkowników online, w tym zalogowanych: 0, gości: 1