今天我们想强调中文搜索功能的挑战。在本文中,我们将讨论CJK语言(中文、日文和韩文)全文搜索实现的主要困难,以及如何借助Manticore Search来克服这些困难。
中文搜索的困难
中文属于所谓的CJK语言家族(中文、日文和韩文)。它们可能是全文搜索实现中最复杂的语言,因为在这些语言中,单词的含义在很大程度上依赖于众多汉字的变体及其顺序,并且字符并没有分割成单词。
中文语言的特点:
- 汉字没有大小写之分。无论上下文如何,它们只有一个概念。
- 字母没有额外的装饰,例如阿拉伯语中的装饰。
- 句子中单词之间没有空格。
那么问题是什么呢?为了在全文搜索中找到精确匹配,我们必须面对分词的挑战,其主要任务是将文本分解为用户可以搜索的低级值单元。
中文的分词/切分
更具体地说,分词是将有意义的数据片段(例如一个单词)转换为一个唯一标识符(称为token)的过程,该标识符在系统中表示一段数据。在全文搜索引擎中,tokens作为对原始数据的引用,但不能用来猜测那些实际的值。
在大多数语言中,我们使用空格或特殊字符将文本分割成片段。然而,在中文和其他CJK语言中,由于其形态特性,这种分割是不可能的。然而,我们仍然需要进行这样的处理。这个过程称为切分。
换句话说,对于中文来说,切分是分词的前提。
以下是一个展示英语和中文分词差异的例子。

如您所见,中文句子短了一半,并且没有任何空格、逗号,甚至没有分割成单词,每个单词在这里由一个或几个汉字表示。以下是一个定量比较:

另一个挑战是,汉字的含义可能会根据它们的顺序和组合而有所不同。让我们看看汉字组合的不同含义:

在这里,我们可以看到两个汉字“简单”的组合,它的意思是“简单性”,但如果我们分别取每个汉字,它们将有不同的含义:“简”(简单)和“单”(单一)。
在某些情况下,根据您在单词之间放置边界的位置,含义可能会不同。例如:

问题是,如您所见,一组字符可以以不同的方式进行切分,从而导致不同的值。
让我们看看解决中文分词/切分问题的可能方法。
实现
对于中文文本切分,有几种方法,但主要有两种:
- N-grams:将“N”个相邻的汉字重叠组视为tokens,其中“N”可以是1 - Uni;2 - Bi;3 - Tri;依此类推“-grams”。
- 基于字典:根据字典进行单词切分。
中文文本切分的最简单方法假设使用N-grams。该算法简单明了,但已知在质量上存在不足,并且随着处理文本长度的增加,开销会显著增加,因为每个N-gram都是一个单独的token,这使得tokens字典变得更大,并使搜索查询的处理变得更加复杂。历史上,这曾是Manticore Search中CJK文本索引的常见方法。
在Manticore Search版本3.1.0中,引入了一种基于ICU文本切分算法的新方法,用于中文文本的切分,该算法遵循第二种方法——基于字典的切分。
使用ICU的好处
ICU是一组开源库,为软件应用程序提供Unicode和全球化支持。除了许多其他功能外,它解决了文本边界确定的任务。ICU算法定位文本范围内的单词、句子、段落的位置,或识别在显示文本时适合换行的位置。
ICU切分在Manticore中的工作算法可以简要描述如下:
- 原始文本被视为符号数组。
- 然后Manticore遍历数组,如果找到一组汉字,它会将其传递给ICU库进行处理。
- 中文文本的切分部分替换原始的未切分部分。
- 其他自然语言处理算法( charset_table 、 wordforms 等)应用于修改后的文本,就像在常见的切分工作流程中一样。
要启用ICU-中文切分,必须设置以下索引配置选项:
morphology = icu_chinesecharset_table = cjk / chinese
互动课程
尝试一下它在我们课程中的工作方式
<img src="ICU_course-1-optimized.webp" alt="img">
如果您尝试我们的“ICU-中文文本分词”互动课程,您可以了解更多关于中文分词的内容,该课程提供了一个命令行以便于学习。
