代码之家  ›  专栏  ›  技术社区  ›  rxmnnxfpvg

MySQL全文搜索表意字符(中文)

  •  4
  • rxmnnxfpvg  · 技术社区  · 16 年前

    我有一个数据库,里面满是亚洲文字记录(中文、日文和韩文),还有拉丁文字记录(英文、法兰西语,你叫它),我想对它们进行全文搜索。

    MySQL说:

    汉字等表意文字 日语没有单词 分隔符。因此,全文 分析器无法确定单词的位置 开始和结束于这些和其他类似的 语言。这意味着 还有一些解决问题的方法 如第11.8节所述, _156;全文搜索功能__。

    第11.8节实际上没有提供解决方法,甚至没有提到问题。

    所以, 如何在混合字符数据库中对单个中文字符进行排序 ? %LIKE% 可以,但它没有漂亮的相关性评级。我应该只计算一个角色出现在记录中的次数,然后按这个顺序排列吗?我很感激你的任何建议。谢谢!

    1 回复  |  直到 11 年前
        1
  •  2
  •   Emil H    16 年前

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

    但是我知道 lucene 运动型分析仪,有中文、日文和韩文,所以我想它对你所做的有些支持。当我需要将Lucene与PHP集成时,我通常做的是将Lucene实现为一个套接字服务器,并从PHP连接到它。

    如果数据集足够小,那么可以选择使用自己的特别方法。这个问题有两个部分:要排名的文档检索和实际排名。检索有几种方法。如果数据集足够小,可以使用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)
    

    然后我将处理每个文档,并为文档中的每个字符(标记)在文档标记表中插入一行。标记unicode字段将包含用于引用此字符的整数unicode序列。token“docfrequency”字段包含一个与文档包含token的次数相对应的整数,而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
    

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

    这让我们剩下的问题是相关性排名,这是你真正要求的。:) 这可以通过使用 Vector Space Model (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
    

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

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

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

    这听起来可能有点复杂,但是如果你对线性代数有一些基本的了解,你可能会在几个小时内产生一个有效的解决方案。不过,如果可能的话,使用现有的解决方案,如Lucene。