2013-12-12 61 views
0

我正在構建一個網站,該網站將具有可搜索的產品數據庫。爲了簡便起見,我的表有三列:試圖在PHP和MySQL中創建關鍵字搜索

  • ID
  • IMG(該產品的圖像的引用)
  • 標籤(VARCHAR 255,用於搜索,前標籤列表「椅子木褐色」)

我有查詢:

$query = "SELECT `img` FROM `products` WHERE `tags` LIKE '%$q%'"; 

這工作正是我怎麼想,與僅限於p問題在於如果標籤按照搜索的順序,它將只選擇行。例如,如果有3行:

  • 行1與標籤「黑盤」
  • 行2與標籤「托盤黑」
  • 行3與標籤「黑托盤層」

當您搜索「黑盤」,都行1和行3將顯示,但不排2.

我試圖讓所有三個行顯示,無論是詞的順序。例如,我想要搜索「黑色托盤」,讓它們全部顯示,但是如果搜索到「托盤層」,則只顯示第3行。也許這需要重新思考原始查詢,我不確定。

非常感謝!

+2

啊哈,黑暗的一個正則表達式的rts – Strawberry

回答

3

您需要使用功能更強大的MATCH AGAINST。另外你可以索引它並提高速度。

參考下以下頁面:

+0

我剛剛接受教育;) – wesside

+1

想到我會伸出援助之手;-) –

+0

我也嘗試過使用它,但我找不到一種方法,因此它只選擇包含所有搜索標籤的行,而不是其中的一些。有沒有辦法做到這一點?非常感謝! –

2

它可能爲時已晚,但如果可能的話,而不是在形式使用另一臺爲您的標籤:

product_id | tag 
1   | black 
1   | tray 
2   | tray 
2   | black 
3   | black 
3   | tray 
3   | layer 

這將允許您查找,當一個或多個標籤使用本的任何產品:

SELECT DISTINCT products.* 
FROM products LEFT JOIN tags ON tags.product_id = products.id 
WHERE tags.tag IN ('black', 'red', 'light') 

編輯

如果你希望所有的標籤是存在,你必須發出X查詢X標籤使用這個搜索:

SELECT * 
FROM 
    (SELECT DISTINCT products.* 
    FROM products LEFT JOIN tags ON tags.product_id = products.id 
    WHERE tags.tag = 'black') AS set_a 
INNER JOIN 
    (SELECT DISTINCT products.* 
    FROM products LEFT JOIN tags ON tags.product_id = products.id 
    WHERE tags.tag ='red') AS set_b ON set_a.product_id = set_b.product_id 
INNER JOIN 
    (SELECT DISTINCT products.* 
    FROM products LEFT JOIN tags ON tags.product_id = products.id 
    WHERE tags.tag = 'light') AS set_c ON set_b.product_id = set_c.product_id 

這將與找到的所有記錄相交,並且只留下潛在記錄。請注意,這是一個非常沉重的請求,我不知道INTERSECT關鍵字是否在MySQL中實現,這將是一個更好的方法,我敢肯定!

+0

這可以工作,但它仍然會選擇具有任何搜索標籤的產品,並且我希望它選擇包含所有搜索標籤的產品。那有意義嗎?有沒有辦法用你的方法來做到這一點?感謝你的幫助! –

+0

這是一個可靠的方法,但我會創建一個索引的緩存表。我會在InnoDB中使用這樣的表來利用FK。但是,您始終可以創建腳本來構建索引的緩存腳本。會更快,再加上你可以利用'MATCH AGAINST' – wesside

+0

如果你想讓所有的標籤出現在你的搜索中,那是一個完全不同的問題。然後,您必須多次發出相同的請求,並使用INTERSECT,這實際上是兩個查詢之間的INNER JOIN。看看我的編輯,馬上發佈! –

0

我會建議存儲單字標籤在一個單獨的關係(表)和:

preg_replace('\s+', "','", $q); 
$query = "SELECT `img` FROM `products` LEFT JOIN `tags` USING (`id`) WHERE `tags`.`content` IN ('$q')";