2011-01-24 55 views
1

我堅持一個相當棘手的問題。我需要某種全文搜索mysql數據庫

我有來自不同倉庫的產品清單,其中每個產品都有:Brand and Model加上一些額外的細節。 Model可能與同一產品的不同倉庫有很大不同,但Brand總是相同。

我在一個表中存儲的所有產品列表,假設它將是Product表。 然後我有另一個表 - Model,與正確的模型名稱,Brand和其他細節如圖像,說明等。另外我有關鍵字列,我嘗試手動添加所有關鍵字。

這裏是問題所在,我需要將從倉庫收到的每個產品與我的Model表中的一條記錄相關聯。現在,我在布爾模式下使用全文搜索,但這非常痛苦,並且效果不佳。我需要做很多手工工作。

這裏是我有名字的只是幾個例子:

  • WINT.SPORT3D
  • WINT.SPORT3D XL
  • WINT.SPORT 3D
  • WINT.SPORT3D MO
  • 冬季運動3D

所有這些項目的正確名稱爲:WINTER SPORT 3D,所以他們都應該被分配到相同的模型。

那麼,有什麼方法可以改善全文搜索或其他技術來解決我的問題嗎?

我正在使用的數據庫是MySQL,我不想改變它。

+0

是一種不可能的品牌`BMW`區分VS產品名稱爲'bmw` ... – ajreal 2011-06-21 16:04:43

回答

1

我會放在一起的表的一個更正式的定義開始:

warehouse: 
    warehouse_id, 
    warehouse_product_id, 
    product_brand, 
    product_name, 
    local_id 

在這裏我使用local_id作爲一個外鍵的「模式」表 - 但要避免進一步的混亂,我會稱之爲'本地'

local: 
    id, 
    product_brand, 
    product_name 

看起來您所描述的表格「產品」是多餘的。

很明顯,直到數據被交叉引用,local_id將爲空。但是,填充後不會有變化,並給予warehouse_id,帶和產品,你可以很容易地找到你的本地描述:

SELECT local.* 
FROM local, warehouse 
WHERE local.id=warehouse.local_id 
AND warehouse.product_brand=local.product_brand 
AND warehouse_id=_____ 
AND warehouse.product_brand=____ 
AND warehouse.product_name=____ 

因此,所有你需要做的是填寫的聯繫。 Soundex是一個相當粗糙的工具 - 更好的解決方案是Levenstein distance algorithm。有一個mysql implementation here

給定一組需要被填充在倉庫表中的行:

SELECT w.* 
FROM warehouse w 
WHERE w.local_id IS NULL; 

...每一行標識爲(使用從以前的查詢中值的最佳匹配爲w 。*)....

SELECT local.id 
FROM local 
WHERE local.product_brand=w.product_brand 
ORDER BY levenstein(local.product_name, w.product_name) ASC 
LIMIT 0,1 

但是,即使2個字符串完全不同,這也會找到最佳匹配!因此......

SELECT local.id 
FROM local 
WHERE local.product_brand=w.product_brand 
AND levenstein(local.product_name, w.product_name)< 
    (IF LENGTH(local.product_name)<LENGTH(w.product_name), 
      LENGTH(local.product_name), LENGTH(w.product_name))/2 
ORDER BY levenstein(local.product_name, w.product_name) ASC 
LIMIT 0,1 

......需要至少一半的字符串匹配。

因此,這可以在一個單一的更新語句來實現:

UPDATE warehouse w 
SET local_id=(
    SELECT local.id 
    FROM local 
    WHERE local.product_brand=w.product_brand 
    AND levenstein(local.product_name, w.product_name)< 
    (IF LENGTH(local.product_name)<LENGTH(w.product_name), 
      LENGTH(local.product_name), LENGTH(w.product_name))/2 
    ORDER BY levenstein(local.product_name, w.product_name) ASC 
    LIMIT 0,1 
) 
WHERE local_id IS NULL; 
+0

謝謝,symcbean。我花了一些時間來實施你的方法,但現在看起來效果更好。再次感謝你 :) – Dimitry 2011-07-08 08:42:53

1

嘗試Soundex。所有示例都解析爲W532,而最後一個解析爲W536。所以,你可以:

  1. 添加列在產品和模式叫SoundexValue並計算出每個產品和型號
  2. 在PRODUCT表比較SOUNDEX值在表型的那些了Soundex值。您可能必須使用範圍(+/- 5)才能獲得更高的匹配率。
  3. 遵循80/20規則。也就是說,將20%的人工努力的80%用於不易掉落的部分。