![]() |
![]() |
![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 5 Pomógł: 0 Dołączył: 17.05.2011 Ostrzeżenie: (0%) ![]() ![]() |
Witam serdecznie,
Tworzę właśnie system do wyszukiwania artykułów i mam problem z napisaniem odpowiedniego, wydajnego zapytania pobierającego dane. Myślę, że rozwiązanie tego mogłoby przydać się również innym użytkownikom forum. Do wyszukiwania artykułów wykorzystywana jest tabela wyszukiwanie o następujących kolumnach: id | id_artykulu | element | slowo | waga Do każdego artykułu przypisane są frazy kluczowe, nazwa oraz treść i w takiej kolejności są dla nas ważne przy wyszukiwaniu. Każdy z tych elementów podzielony jest na pojedyncze słowa. Aby dany artykuł mógł zostać wyświetlony powinniśmy znaleźć wszystkie wyszukiwane słowa w danym elemencie, przy czym każde znalezione słowo otrzymuje punktację wagową. Np. wyszukiwana fraza "piękna zima" otrzyma 2 000 000 pkt. wyszukana wśród fraz kluczowych, 20 000 w nazwie, 200 w treści. Wartości te nie sumują się w razie znalezienia w kilku elementach. Jeśli znajdziemy we frazie kluczowej to dalsze elementy nas nie interesują - tylko jeden, najwyżej oceniany element. Artykuł w tabeli wyszukiwania może więc wyglądać następująco (dwie frazy kluczowe, nazwa, treść): id | id_artykulu | element | slowo | waga ------------------------------------------------------ 1 | 1 | 1 | piękna | 1000000 1 | 1 | 1 | zima | 1000000 1 | 1 | 2 | ładne | 1000000 1 | 1 | 2 | lato | 1000000 1 | 1 | 3 | jakaś | 10000 1 | 1 | 3 | nazwa | 10000 1 | 1 | 4 | tresc | 100 1 | 1 | 4 | tego | 100 1 | 1 | 4 | artykulu | 100 Dane do wyświetlenia pobieramy z tabeli artykuly o następujących kolumnach: id | nazwa | tresc | waga_dodatkowa | top | aktywny Waga dodatkowa powinna być dodawana do obliczonej wagi w znalezionym elemencie. Jeśli artykuł ma 1 w kolumnie "top" to powinien być pozycjonowany wg wag na samej górze. Potem wyświetlamy artykuły o top = 0. Oczywiście bierzemy również pod uwagę kolumnę "aktywny". Teraz pytanie: jak napisać najbardziej optymalne zapytanie pobierające artykuły (powiedzmy 10 z danego przedziału) jak i również ilość wszystkich znalezionych artykułów (na potrzeby dzielenia na strony)? Próbowałem wstępnie pobrać aby samą listę artykułów, jednak otrzymują zdublowane wyniki, tzn. jeśli coś zostało znalezione w jednym artykule w 2 miejscach to otrzymuję to dwa razy. Zapytanie, które wykonuję:
Działa to jednak tylko w przypadku, gdy w kolumnie "element" znajdują się unikalne wartości dla każdego elementu, tak więc musiałbym tam mieć np. "1_1" itd. gdzie pierwsza liczba to id artykułu. Pozdrawiam serdecznie i dziękuję z góry za pomoc. EDIT ----------------------------- Dodam jeszcze, że ilość rekordów może być liczona nawet w milionach tak więc fajnie, gdyby było to dość wydajne rozwiązanie ![]() Ten post edytował adam_c 28.12.2011, 18:09:59 |
|
|
![]() |
![]()
Post
#2
|
|
Grupa: Zarejestrowani Postów: 5 Pomógł: 0 Dołączył: 17.05.2011 Ostrzeżenie: (0%) ![]() ![]() |
Witam,
Dzięki za odpowiedzi ![]() Skrypt będzie działał na hostingu współdzielonym, tak więc mam ograniczone możliwości. Zaktualizowałem nieco bazę i zapytanie i jest prawie dobrze. W tej chwili tabele bazy wyglądają tak: Tabela "artykuly": id | nazwa | tresc | dodatkowa_waga | top | aktywny Tabela "search_indeksy": id | slowo Tabela "search_rodzaje_elementow": id | nazwa | waga Tabela "search_wyszukiwanie": id | id_matki | numer_elementu | rodzaj_elementu | indeks Samo zapytanie brzmi tak (pomijam wyszukiwanie indeksów, wcześniej pobrałem je do tablicy $wyszukiwane):
Wszystko byłoby super, gdyby nie pierwsza część czyli DISTINCT(t2.id). Wydawało mi się, że powinno to działać tak, że nie pobierze mi np. artykułu 1, a tak się nie dzieje, a raczej dzieje się ale nie do końca. Powiedzmy, że znaleziono wyszukiwane słowa w dwóch tagach artykułu 1 oraz w jego nazwie. Logiczne byłoby pozostawienie wyszukania z taga (wyższa waga), pominięcie drugiego oraz tego z nazwy. W praktyce jednak drugi wyszukany element (drugi tag) zostaje pominięty, jednak element wyszukany po nazwie pozostaje. Wygląda na to, że zapytanie odrzuciło drugi wyszukany element po tagu, bo był całkowicie identyczny, a w trzecim zmieniła się waga (nazwa ma mniejszą) więc jest już coś innego i nie wywala go. Nieco namieszałem ale mam nadzieję, że wiadomo o co chodzi. Jak to rozwiązać? Macie pomysły? ![]() EDIT ------------------------ Witam ponownie, Udało mi się napisać odpowiednie zapytanie. Nie jest może ono za krótkie, ale zdaje egzamin i pobiera co trzeba:
Co o tym sądzicie? Nie wspomniałem wcześniej, że "numer_elementu" w tabeli "wyszukiwanie" składa się z id_matki i kolejnego numeru elementu (np. 1_1 dla pierwszego taga artykułu 1). Teraz wystarczy tylko LIMIT i można dzielić na strony. Czy pobranie ilości wszystkich znalezionych artykułów drugim zapytaniem z COUNT ale bez ORDER będzie najbardziej odpowiednie, czy jest jakieś lepsze rozwiązanie? Pozdrawiam Ten post edytował adam_c 29.12.2011, 10:21:45 |
|
|
![]() ![]() |
![]() |
Wersja Lo-Fi | Aktualny czas: 26.06.2025 - 06:26 |