2011-08-29 16 views
7

Próbuję utworzyć wyszukiwarkę dla witryny opartej na inwentarzu. Problem polega na tym, że mam informacje wewnątrz bbtags (jak w [b]test[/b] sentence, wartość test powinna być wyceniona na 3, natomiast sentence powinna być wyceniona na 1).Zapytania mysql PHP

Oto przykład z indeksu:
My test sentence, my my (ma SKU od TST-DFS)
bazy danych:

|Product| word |relevancy| 
| 1 | my | 3 | 
| 1 | test | 1 | 
| 1 |sentence| 1 | 
| 1 | TST-DFS| 10 | 

Ale w jaki sposób dopasować TST-DFS jeśli użytkownik wpisze w TST DFS? Chciałbym, żeby ten SKU miał trafność powiedzmy 8, zamiast pełnego 10 ..

Słyszałem, że funkcja wyszukiwania FULL TEXT w MySQL pomogłaby, ale nie mogę znaleźć dobrego sposobu na Zrób to. Chciałbym unikać takich rzeczy, jak UNION, i utrzymywać zapytanie tak optymalizowane, jak to tylko możliwe.

Każda pomoc przy wymyśleniu dobrego systemu byłaby świetna.

Dzięki Max

+0

Nie można użyć 'możliwości FULLTEXT' MySQL, czy to co masz na myśli mówiąc„indeks”? – Bojangles

+0

Problem polega na tym, że mam dużo informacji, które są ważne, ale FULLTEXT MySQL nie wie, że jest ważny (jak numery sku, nazwa produktu i inne określone słowa). Więc indeksuję każde słowo w każdym produkcie i nie wierzę, że FULLTEXT MySQL pomoże mi przeszukać każdy z wierszy. – Ben

+0

O rację. O ile widzę, nie, "FULLTEXT" nie byłoby w ogóle użyteczne. Szkoda naprawdę, ponieważ jest to wspaniała część MySQL. – Bojangles

Odpowiedz

5

Ale w jaki sposób mogę dopasować TST-DFS, jeśli użytkownik wpisał w TST DFS?
chciałbym że SKU mieć trafności powiedzieć 8, zamiast pełnej 10 ..

Jeśli mam rację pytanie, odpowiedź jest rzeczywiście łatwe.
Cóż, jeśli forge twoje zapytanie trochę przed wysłaniem do mysql.

OK, załóżmy, że mamy $query i zawiera ona TST-DFS.

Czy skupimy się na rozpiętości słów? Przypuszczam, że powinniśmy, jak większość wyszukiwarek, więc:

$ok=preg_match_all('#\w+#',$query,$m); 

Teraz jeśli wzór dopasowany ... $m[0] zawiera listę słów w $query.
Można to dostosować do kodu SKU, ale dopasowanie do pełnych słów w trybie ORAZ jest podobne do tego, co zakłada użytkownik. (Jak to się dzieje na google i yahoo)

Następnie musimy ugotować $expr wyrażenie zostanie wstrzyknięty do naszego ostatecznego zapytania.

if(!$ok) { // the search string is non-alphanumeric 
    $expr="false"; 
} else { // the search contains words that are no in $m[0] 
    $expr=''; 
    foreach($m[0] as $word) { 
    if($expr) 
     $expr.=" AND "; // put an AND inbetween "LIKE" subexpressions 
    $s_word=addslashes($word); // I put a s_ to remind me the variable 
           // is safe to include in a SQL statement, that's me 
    $expr.="word LIKE '%$s_word%'"; 
    } 
} 

Teraz $expr powinien wyglądać "words LIKE '%TST%' AND words LIKE '%DFS%'"

z tą wartością, możemy zbudować ostateczną zapytanie:

$s_expr="($expr)"; 
$s_query=addslashes($query); 

$s_fullquery= 
"SELECT (Product,word,if((word LIKE '$s_query'),relevancy,relevancy-2) as relevancy) ". 
"FROM some_index ". 
"WHERE word LIKE '$s_query' OR $s_expr"; 

który otrzymuje następujące, dla "TST-DFS":

SELECT (Product,word,if((word LIKE 'TST-DFS'),relevancy,relevancy-2) as relevancy) 
FROM some_index 
WHERE word LIKE 'TST-DFS' OR (word LIKE '%TST%' AND word LIKE '%DFS%') 

Jak widać, w pierwszej linii SELECT, jeśli mecz jest częściowa, będzie mysql powrócić trafności-2

W trzecim klauzula WHERE, jeśli nie pełny mecz, $s_expr, częściowe zapytanie mecz gotowane z góry, jest sądzony zamiast.

+0

poprawione. moja logika była zła. ** Teraz ** '$ expr' powinno wyglądać tak, jak' words LIKE '% TST%' AND words LIKE '% DFS%' ' – ZJR

+0

Więc gdzie się znajduje kolumna" relevancy "? – Ben

+0

Nigdy nie myśl o powyższym, jak by to działało z zapytaniem wielowyrazowym? Wygląda na to, że porównuje się albo doskonale ze słowem, albo zawiera wszystkie subwords, czy mam rację co do tego? – Ben

0

Chciałbym dodać kolumnę, która jest pozbawione wszelkich szczególnym charakterze, w pisowni, a następnie upcased (lub utworzyć funkcję, która porównuje na tekście, który został rozebrany i upcased). W ten sposób twoja trafność będzie spójna.

2

Lubię wszystko małymi literami i rozebrać się znaki specjalne (jak w numerze telefonu lub kartą kredytową biorę wszystko na obu stronach, że nie jest liczbą)

1

Zamiast próbować stworzyć własną FTS rozwiązaniem, możesz spróbować dopasować silnik MySQL FTS do swoich wymagań. To, co widziałem, to stworzyć nową tabelę do przechowywania danych FTS. Utwórz kolumnę dla każdej innej części danych, która ma mieć inną istotność. Dla twojego pola sku możesz przechowywać surowy sku, ze spacjami, podkreśleniami, łącznikami i innymi specjalnymi postaciami. Następnie przechowuj rozebraną wersję z usuniętymi wszystkimi tymi rzeczami. Możesz również chcieć zapisać wersję z usuniętymi zerami, ponieważ ludzie często opuszczają takie rzeczy. Możesz przechowywać wszystkie te odmiany w tej samej kolumnie. Przechowuj nazwę produktu w innej kolumnie, a opis produktu w innej kolumnie. Utwórz oddzielny indeks w każdej kolumnie. Następnie, gdy przeprowadzasz wyszukiwanie, możesz przeszukiwać każdą kolumnę indywidualnie i pomnażać rangę wyników w oparciu o to, jak ważna jest Twoja kolumna. Możesz więc pomnożyć wyniki sku przez 10, tytuł po 5 i pozostawić opis w niezmienionym stanie. Być może trzeba będzie trochę eksperymentować, aby uzyskać pożądane wyniki, ale ostatecznie może być prostsze niż tworzenie własnego indeksu.

+0

Mam bbcode, który otacza napisy w opisie. czy mogę wziąć wszystko między bbcodes i połączyć wszystkie światy razem (z odstępami między nimi) w jednej kolumnie i pomnożyć tę kolumnę przez powiedzmy 3? Czy możesz podać prosty przykład wykorzystania pełnego tekstu z różnymi mnożnikami? – Ben

+0

Jeśli chcesz rozwinąć swoją odpowiedź, z przyjemnością dodam nagrodę do tego pytania. – Ben

1

Utwórz tabelę słów kluczowych. Coś w stylu:

Do tej tabeli przypisz wszystkie możliwe słowa kluczowe, skus itp. Utworzyć inną tabelę, most post-słowa kluczowe, (zakładając postId id jest już przypisany w oryginalnej tabeli) wzdłuż linii:

integer keywordId | integer postId 

Gdy masz to, można łatwo dodawać słowa kluczowe do każdego posta jak to jest zainteresowane. Aby obliczyć całkowitą wartość punktową dla danego stanowiska, zapytanie takie jak poniższe powinno wystarczyć:

SELECT sum(pointValue) FROM keywordPostsBridge kpb 
JOIN keywords k ON k.keywordId = kpb.keywordId 
WHERE kpb.postId = YOUR_INTENDED_POST 
1

Myślę, że rozwiązanie jest dość proste, chyba że coś przeoczyłem.

Zasadniczo uruchom dwa wyszukiwania, jeden to dopasowanie dokładne, drugi to dopasowanie lub dopasowanie do wyrażenia regularnego.

Połącz dwa zestawy wyników razem, np. Dopasuj dopasowanie dopasowania lewy dołącz. Na przykład:

final_relevancy = (IFNULL(like_relevancy, 0) + IFNULL(exact_relevancy, 0) * 3)/4 

Ja sam tego nie próbowałem. Tylko pomysł.

0
/* 
q and q1 - you table 
this query takes too much resources, 
make from it update-query (scheduled task or call it on_save if you develop new system) 
*/ 
SELECT 
     CASE 
       WHEN word NOT REGEXP "^[a-zA-Z]+$" 
        /*many replace with junk characters 
        or create custom function 
        or if you have full db access install his https://launchpad.net/mysql-udf-regexp 
        */ 
       THEN REPLACE(REPLACE(word, '-', ' '), '#', ' ') 
       ELSE word 
     END word , 
     CASE 
       WHEN word NOT REGEXP "^[a-zA-Z]+$" 
       THEN 8 
       ELSE relevancy 
     END   relevancy 
FROM (SELECT 'my' word, 
       3  relevancy 

     UNION 

     SELECT 'test' word, 
       1  relevancy 

     UNION 

     SELECT 'sentence' word, 
       1   relevancy 

     UNION 

     SELECT 'TST-DFS' word, 
       10 relevancy 
     ) 
     q 

UNION 

SELECT * 
FROM (SELECT 'my' word, 
       3  relevancy 

     UNION 

     SELECT 'test' word, 
       1  relevancy 

     UNION 

     SELECT 'sentence' word, 
       1   relevancy 

     UNION 

     SELECT 'TST-DFS' word, 
       10 relevancy 
     ) 
     q1 
0
it is a page coading where query result shows 

**i can not use functions by use them work are more easier** 

<html> 
<head> 
</head> 
<body> 
<?php 
//author S_A_KHAN 
//date 10/02/2013 
$dbcoonect=mysql_connect("127.0.0.1","root"); 
if (!$dbcoonect) 
{ 
die ('unable to connect'.mysqli_error()); 
} 
else 
{ 
echo "connection successfully <br>"; 

} 
$data_base=mysql_select_db("connect",$dbcoonect); 


if ($data_base==FALSE){ 

die ('unable to connect'.mysqli_error($dbcoonect)); 
    } 
else 
    { 
echo "connection successfully done<br>"; 
    ***$SQLString = "select * from user where id= " . $_GET["search"] . ""; 
$QueryResult=mysql_query($SQLString,$dbcoonect);*** 

echo "<table width='100%' border='1'>\n"; 
    echo "<tr><th bgcolor=gray>Id</th><th bgcolor=gray>Name</th></tr>\n"; 
    while (($Row = mysql_fetch_row($QueryResult)) !== FALSE) { 
     echo "<tr><td bgcolor=tan>{$Row[0]}</td>"; 
     echo "<td bgcolor=tan>{$Row[1]}</td></tr>"; 
    } 
} 
?> 

</body> 
</html>