4

我有一个充满亚洲字符填充记录(中文、日语和韩文)的数据库,以及那些带有拉丁字符填充记录(英语、法语,你能想到的)的数据库,我想对它们执行全文搜索。

MySQL 说:

汉语和日语等表意语言没有单词分隔符。因此,FULLTEXT 解析器无法确定这些语言和其他此类语言中单词的开始和结束位置。第 11.8 节“全文搜索功能”中描述了此问题的含义和一些解决方法。

11.8 节实际上没有提供变通方法,甚至没有提到这个问题。

那么,如何对混合字符数据库中单个汉字的搜索进行排序呢?%LIKE%会起作用,但它没有漂亮的相关性评级。我应该只计算一个角色出现在记录中的次数,然后按此排名吗?我很感激你的任何建议。谢谢!

4

1 回答 1

2

这取决于数据集的大小。如果我们谈论数十万行,我可能会看看可用的优秀独立全文搜索解决方案之一。我实际上从来没有处理过mysqlf这个问题,所以我不确定哪些解决方案包括对亚洲语言的支持。

然而,我确实知道lucene支持中文、日文和韩文的分析器,所以我的猜测是它对你正在做的事情有某种支持。当我需要集成 lucene 和 php 时,我通常会做的是将 lucene 实现为套接字服务器,并从 php 连接到它。

如果数据集足够小,则可以选择推出自己的 ad-hoc 方法。这个问题有两个部分:检索要排名的文档,以及实际排名。有几种方法可以进行检索。如果您的数据集足够小,一种可能是使用 LIKE。另一个可能是推出您自己的基于磁盘的索引方案,尽管这会相当复杂和耗时。您也可以使用 MySQL 作为中间路径,如下所述。

为了使用 MySQL 实现索引方案,您必须创建一些具有以下结构的表:

document
  document_id
  document_text
  document_tokencount

document_token
  document_id
  token_id
  token_docfrequency
  index (token_id, document_id)

token
  token_id
  token_unicode
  token_globalfrequency
  index (token_unicode)

然后我会处理每个文档,并为文档中的每个字符(令牌)在 document_token 表中插入一行。token_unicode 字段将包含用于引用此字符的整数 unicode 序列。token_docfrequency 字段包含一个整数,对应于文档包含令牌的次数,而 token_globalfrequency 字段包含在所有文档中使用该术语的总次数。

这将允许您快速搜索令牌:

SELECT * FROM document_token WHERE token_id = 1
UNION
SELECT * FROM document_token WHERE token_id = 2
UNION
SELECT * FROM document_token WHERE token_id = 3

(联合方法是一种 hack,它允许 mysql 为所有选择利用索引,并且很可能比使用单个 select 和多个 or 语句的相应查询更快)

这给我们留下了相关性排名作为剩下的问题,这是您真正要求的。:)这可以通过利用向量空间模型 (VSM)来完成,效果非常好。

进行搜索后,您要做的第一件事是计算此令牌的tf-idf分数。这是使用以下公式完成的:

tf-idf = tf(t,d) / tf(d) * log(D / d(t))

where:
tf(t,d) = token frequency in current document
tf(d) = total number of tokens in current document
D = total number of documents
d(t) = number of document that contains the token

首先为搜索查询中的每个词计算这个分数,并将结果存储在 hashmap 或类似的东西中。这是您的第一个向量,称为 v_1。然后继续第一个文档。计算文档中每个术语的 tf-idf 分数,并将其存储为 v_2。现在您可以使用cosine similiarity计算此文档的分数:

score = arccos(v_1 * v_2 / (|v_1| * |v_2|))

结果是一个可用于对文档进行排名的值。继续并为每个文档执行此操作。按降序对它们进行排序。列表中的第一个文档将是最相关的文档。

这听起来可能有点复杂,但如果你对线性代数有一些基本的了解,你可能会在几个小时内得出一个可行的解决方案。尽管如此,如果可能的话,请使用现有的解决方案,例如 lucene。

于 2009-05-03T15:53:49.617 回答