2011-06-27 20 views
21

Oto, co chcę zrobić:Najlepszy sposób na ważone wyszukiwanie w wielu polach w mysql?

  • mecz wyszukiwania obiektów pod wielu dziedzinach mojego stolika
  • zamówienia wyniki według znaczenia dziedzinie i znaczenia w dobieraniu (w tej kolejności)

Np: załóżmy, że mam bloga. Następnie ktoś wyszukuje hasło "php". Wyniki wydaje się w ten sposób:

  • pierwsze mecze w polu „tytułem”, uporządkowane według trafności
  • Następnie, odpowiadających na polu „ciała”, uporządkowane według trafności zbyt
  • a więc on z określonymi polami ...

Tak naprawdę zrobiłem to z klasą w PHP, ale używa ona wielu UNION (dużo!) i rośnie wraz z wielkością tematu wyszukiwania. Martwię się więc o wydajność i problemy z DOS-em. Czy ktoś ma o tym pojęcia?

Odpowiedz

29

Prawdopodobnie podejście to robić ważoną Search/wyników jest odpowiednia dla Ciebie:

SELECT *, 
    IF(
      `name` LIKE "searchterm%", 20, 
     IF(`name` LIKE "%searchterm%", 10, 0) 
    ) 
     + IF(`description` LIKE "%searchterm%", 5, 0) 
     + IF(`url`   LIKE "%searchterm%", 1, 0) 
    AS `weight` 
FROM `myTable` 
WHERE (
    `name` LIKE "%searchterm%" 
    OR `description` LIKE "%searchterm%" 
    OR `url`   LIKE "%searchterm%" 
) 
ORDER BY `weight` DESC 
LIMIT 20 

Używa select podzapytanie zapewnić ciężar zamawiania wyniki. W takim przypadku można przeszukać trzy pola, można określić wagę na pole. Jest to prawdopodobnie tańsze niż związki i prawdopodobnie jeden z szybszych sposobów w zwykłym MySQL.

Jeśli masz więcej danych i potrzebujesz szybszych wyników, możesz rozważyć użycie czegoś takiego jak Sphinx lub Lucene.

+0

Podoba mi się to podejście! czy możesz wyjaśnić mi, co się dzieje w IF przed FROM? nie jestem używany ze złożonymi pytaniami =/ –

+2

Zasadniczo jest to funkcja IF, jeśli warunek (pierwszy argument) jest prawdziwy, użyty zostanie drugi argument (waga), w przeciwnym razie zostanie użyty trzeci argument (0-waga). Instrukcja zawiera wszystkie szczegóły: http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#function_if – hakre

+0

to bardzo miłe! więc jeśli pojawi się w nazwie (nie na początku), opisie i adresie URL, otrzyma wagę 16? (10 + 5 + 1) –

1

Powinieneś użyć dedykowanego indeksera, aby wstępnie pobrać wszystkie dane do zoptymalizowanego indeksu z możliwością wyszukiwania. Sphinx i podobne produkty robią to bardzo dobrze.

8

możesz dodać wiele mysql wartości MATCH() razem, najpierw mnożąc każdy przez ich wagę.

uproszczone oczywiście ...

'(MATCH(column1) AGAINST(\''.$_GET['search_string'].'\') * '.$column1_weight.') 
+ (MATCH(column2) AGAINST(\''.$_GET['search_string'].'\') * '.$column2_weight.') 
+ (MATCH(column3) AGAINST(\''.$_GET['search_string'].'\') * '.$column3_weight.') 
AS relevance' 

następnie

'ORDER BY relevance' 
+0

, jeśli twoje ciężary są prawidłowo ustawione, umieści je w żądanej kolejności. – dqhendricks

+0

czy możesz podać przykład, jak ustawić wagę do tego? –

+0

@hugo_leonardo wagi zależą od tego, o ile ważniejszy jest mecz w tytule od ciała. więc jeśli mecz o tytuł jest 5 razy ważniejszy niż dopasowanie do ciała, waga będzie wynosić odpowiednio 5 i 1. Czy to ma sens? – dqhendricks

1

miałem dokładnie ten sam pytanie i to był w pełni odpowiedział na jednym z forów MySQL. Here's the thread. Coś w rodzaju długiej nici (ponieważ jestem trochę zdyszana), ale wypłata jest tym, czego szukasz.

+0

bardzo interesujące! +1 (: –

+0

@hugo_leonardo - tak, dwóch gości, którzy odpowiedzieli, udzieliło bardzo przemyślanych odpowiedzi: –

+2

@PeteWilson: proszę dodać odpowiednie cytaty do swojego postu, ponieważ linki zewnętrzne mogą się zepsuć. – jor

Powiązane problemy