我需要在mysql数据库上进行某种全文搜索

时间:2011-01-24 00:34:19

标签: mysql full-text-search grouping

我遇到了一个非常棘手的问题。

我有来自不同仓库的产品清单,每个产品都有:Brand and Model以及一些额外的细节。 Model可能与同一产品的不同仓库有很大不同,但Brand始终相同。

我存储在一个表中的所有产品列表,假设它将是Product表。 然后我有另一张表格Model正确的模型名称Brand以及其他详细信息,例如图片,说明等。另外我还有关键字列,我尝试添加所有关键字手动

问题是,我需要将从仓库收到的每个产品与我Model表中的一条记录相关联。现在我在布尔模式下使用全文搜索,但这非常痛苦并且不能很好地工作。我需要做很多手工工作。

以下是我所拥有的几个名字的例子:

  • WINT.SPORT3D
  • WINT.SPORT3D XL
  • WINT.SPORT 3D
  • WINT.SPORT3D MO
  • WINTER SPORT 3D

所有这些项目的正确名称为:WINTER SPORT 3D,因此它们应全部分配到同一模型。

那么,有没有办法改进全文搜索或其他技术来解决我的问题?

我正在使用的数据库是MySQL,我宁愿不改变它。

2 个答案:

答案 0 :(得分:1)

试试Soundex。所有示例都解析为W532,而最后一个解析为W536。所以,你可以:

  1. 向名为SoundexValue的PRODUCT和MODEL添加一列,并计算每种产品和型号的Soundex值
  2. 将PRODUCT表中的Soundex值与模型表中的值进行比较。您可能必须使用范围(+/- 5)才能获得更高的匹配率。
  3. 遵循80/20规则。也就是说,将80%的手动工作花费在不容易失败的20%上。

答案 1 :(得分:1)

我首先要对表格进行更正式的定义:

warehouse:
    warehouse_id,
    warehouse_product_id,
    product_brand,
    product_name,
    local_id

在这里,我使用local_id作为“模型”表的外键 - 但为了避免进一步混淆,我将其称为“本地”

local:
    id,
    product_brand,
    product_name

您所描述的“产品”表似乎是多余的。

显然,在数据交叉引用之前,local_id将为null。但是在填充之后它将不必更改,并且给定了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;