2011-01-24 59 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%用于不易掉落的部分。