文本分析是将非结构化文本(例如电子邮件的正文或产品说明)转换为针对搜索优化的结构化格式的过程。
当对text
字段建立索引或搜索时,Elasticsearch 会执行文本分析。
但是,如果您使用text字段或文本搜索未返回预期的结果,则配置文本分析通常会有所帮助。如果您正在使用Elasticsearch执行以下操作,则还应该研究分析配置:
文本分析使Elasticsearch能够执行全文搜索,其中搜索返回所有相关结果,而不仅仅是精确匹配。
如果您进行搜索Quick fox jumps
,则可能需要包含的文档:A quick brown fox jumps over the lazy dog
,还可能需要包含诸如fast fox
或的相关单词的文档foxes leap
。
分析使得标记化的全文搜索成为可能。将文本分解成为较小的块,成为标记(token
)。在英语语义下,通常为单个单词。
如果您将词组索引the quick brown fox jumps
为单个单词,并且用户搜索的时quick fox
,则不会将其视为匹配项。但是,如果您对短语进行标记,并分别索引单个单词,则可以单独查询字符串中的术语,这意味着他们可以通过搜索进行匹配quick fox
,fox brown
或其他变化。
tokenization 可以匹配单个术语,但每个标记仍是机械的匹配,这就意味着:
1. quick
和Quick
不会匹配,即使是你希望它们之间会相互匹配。
2. fox
和foxes
拥有相同的词根,但也不会相互匹配
3. 同义词之间也不会相互匹配
为了解决这些问题,文本分析可以将这些标记标准化为标准格式。这样,您就可以匹配与搜索字词不完全相同但足够相似但仍具有相关性的标记。
为了保证搜索的准确性,您可以把搜索时的文本分析和索引里的文本分析设置为一致。
文本分析由分析器执行,它是控制整个过程的一组规则。
Elasticsearch包含一个默认的分析器,称为 标准分析器,它对于开箱即用的大多数用例都适用。
如果要定制搜索体验,则可以选择其他 内置分析仪,甚至可以 配置自定义分析仪。定制分析器使您可以控制分析过程的每个步骤,包括:
比较有名的中文分词器
一个分析器,无论是内置的还是自定义的,都是一个包,包含三个最基本的模块:character filters, tokenizers, and token filters
内置的分析器将这些构件预先打包为适合不同语言和文本类型的分析器。Elasticsearch还公开了各个构建基块,以便可以将它们组合以定义新的custom分析器。
一个character filters
接受一个原始的文本,作为一个字符串的流,并且可以添加,移除,改变。一个分析器,可能会拥有零个或者多个character filters
,按照一定的顺序使用。
一个tokenizer
接受一个字符流,将他们拆分成独立的标记,并输出。
分词器还负责记录每个术语的顺序或位置以及该术语代表的原始单词的开始和结束字符偏移量。
分析器必须仅具有一个标记器。
一个token filters
接受一个标记流,可能会添加、移除、改变一个标记。但是不允许改变,标记在原文本中的位置或者字符的偏移量。分析器可能具有零个或多个按顺序应用的令牌过滤器。
文本分析会出现在两种情况下:
每次使用的分析器或一组分析规则分别称为索引分析器或搜索分析器。
在默认情况下,或是说,在大多数情况下,会使用相同的分析器。确保搜索和索引的一致性。
示例
The QUICK brown foxes jumped over the dog!
分析成,[ quick, brown, fox, jump, over, dog ]
可以使用下面的API,来获取文本分析结果
GET /_analyze
{
"analyzer" : "standard",
"text" : ["this is a test", "the second text"]
}
Stemming 就是将原单词,还原成词根的形式。这样就保证在搜索过程中,匹配单词的变体。在某些情况下,词干的词根形式可能不是真实的词,但这不影响搜索。如果将单词的所有变体都简化成为相同的词根形式,则他们将会正确的匹配。
在Elasticsearch 中,抽取词干是由stemmer token filter完成的,这些过滤器可以基于一定的方法完成。
这种词干抽取器,为每个词提供一系列规则,将其简化为词根形式。
优点:
但是,大多数算法词干仅会更改单词的现有文本。这意味着它们可能不适用于不包含其词根形式的不规则单词。
以下是常用的算法:
stemmer
,它提供了几种语言的算法词干,其中一些带有其他变体。kstem
,是英语的词干分析器,它将算法词干与内置词典结合在一起。porter_stem
,是我们推荐的英语算法提取器。snowball
,它对几种语言使用 基于Snowball的词干规则。查找提供的字典中的词,使用字典中的词干。
在实践中,算法词干分析器通常优于字典词干分析器。这是因为词干分析器具有以下缺点:
有些时候,词干分析器会将拼写类似但是含义不同的词,定义为同一个词干。为了防止这种情况,可以使用control stemming,如下所示:
stemmer_override
,可让您定义用于阻止特定令牌的规则。
keyword_marker
,将指定的标记标记为关键字。关键字令牌不会被后续的词干令牌过滤器阻止。
conditional
,可用于将令牌标记为关键字,类似于keyword_marker过滤器。
对于内置的语言分析器,您还可以使用参数stem_exclusion
来制定不会被阻之的单词列表。
当tokenizer将文本转化成标记流时,他还会记录以下内容:
使用这些信息,您可以为流创建一个有向无环图,成为tonen graphs。在图中,每个位置代表一个节点。每个标记都表示只想下一个位置的边或弧。
一些标记过滤器可以将新的标记添加到现有的流中。同义词通常与现有的标记的位置相同。
在默认情况下,Elasticsearch 使用默认的标准分析器,对于大多数语言,是开箱即用的。
如果默认的标准分析器不符合您的需求,可以尝试使用Elasticsearch 提供的其他分析器,内置分析仪不需要配置,但是可以使用一些支持选项来调整其行为。例如,您可以为标准分析器配置要删除的自定义停用词列表。
最简单的用法
POST _analyze
{
/*指定分析器*/
"analyzer": "whitespace",
/*指定要分析的文本*/
"text": "The quick brown fox."
}
指定其他参数
POST _analyze
{
"tokenizer": "standard",
"filter": [ "lowercase", "asciifolding" ],
"text": "Is this déja vu?"
}
使用现有的索引中文本字段的分析器
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"std_folded": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"asciifolding"
]
}
}
}
},
"mappings": {
"properties": {
"my_text": {
"type": "text",
"analyzer": "std_folded"
}
}
}
}
GET my_index/_analyze
{
"analyzer": "std_folded",
"text": "Is this déjà vu?"
}
GET my_index/_analyze
{
"field": "my_text",
"text": "Is this déjà vu?"
}
标准分析器可以开箱即用,但也可以修改一些配置来控制它的行为。例如,可以将标准分析器配置为支持停用词列表。参考下面示例:
std_english
分析器,但是配置为删除英语停用词的预定义列表GET
示例中,my_text
字段直接使用标准分词器,没有被移除停止使用后的词,结果是[the, old, brown, cow]
my_text.english
使用std_english
分词器,会移除停止使用的词,结果是[old, brown, cow]
PUT my_index
{
"settings": {
"analysis": {
"analyzer": {
"std_english": {
"type": "standard",
"stopwords": "_english_"
}
}
}
},
"mappings": {
"properties": {
"my_text": {
"type": "text",
"analyzer": "standard",
"fields": {
"english": {
"type": "text",
"analyzer": "std_english"
}
}
}
}
}
}
POST my_index/_analyze
{
"field": "my_text",
"text": "The old brown cow"
}
POST my_index/_analyze
{
"field": "my_text.english",
"text": "The old brown cow"
}
当标准分析器无法满足使用需求是,可以自定义一个分析器:
参数 | 含义 |
---|---|
tokenizer | 内置或自定义的标记器。(需要) |
char_filter | 内置或自定义字符过滤器的可选数组 。 |
filter | 内置或自定义标记过滤器的可选数组 。 |
position_increment_gap | 在为文本值数组建立索引时,Elasticsearch在一个值的最后一项和下一个值的第一项之间插入一个假的“空白”,以确保词组查询与来自不同数组元素的两项不匹配。默认为100。查看position_increment_gap更多。 |
可以点击查看示例
Elasticsearch 提供了多种方法来指定内置或自定义的分析器:
把事情简单化,在不同层次和不同的时间,指定分析仪的灵活性是伟大的… 不过也要仅在需要时它。
在大多数情况下,一种简单的方法最有效:为每个text
字段指定一个分析器,如为 字段指定分析器中所述。这种方法与Elasticsearch的默认行为很好地配合使用,使您可以使用同一分析器进行索引和搜索。它还使您可以使用get mapping API
快速查看哪个分析器应用于哪个字段。如果通常不为索引创建映射,则可以使用 索引模板来达到类似的效果。
Elasticsearch 依次检查以下参数,来确定要使用的索引分析器:
1. analyzer
,字段映射参数
2. analysis.analyzer.default
,默认分析器
3. 如未指定,则使用标准分析器
在大多数情况下,无需指定其他搜索分析器。这样做可能会对相关性产生负面影响,并导致意外的搜索结果。
如果您选择指定一个单独的搜索分析器,我们建议您在部署到生产环境之前彻底 测试您的分析配置。
在搜索时,Elasticsearch通过依次检查以下参数来确定要使用的分析器:
analyzer
搜索查询中 的参数。请参阅为查询指定搜索分析器。search_analyzer
字段 的映射参数。请参阅为字段指定搜索分析器。analysis.analyzer.default_search
。请参阅为索引指定默认搜索分析器。analyzer
字段 的映射参数。请参阅为字段指定分析器。可以点击查看示例
Standard Analyzer
):根据Unicode文本分段算法的定义,分析器将文本划分为单词边界上的多个术语。它删除大多数标点符号,小写术语,并支持停用词Simple Analyzer
):当分析器遇到非字母的字符时,它将文本划分成为多个术语,将所有术语转化为小写Whitespace Analyzer
):任何空白字符都作为分隔符,将文本划分为术语Stop Analyzer
):和简单分析器类似,而且支持去除停用词。Keyword Analyzer
):将整个文本视为一个术语Pattern Analyzer
):使用正则表达式,将文本分割。支持小写文本,和停用词Language Analyzer
):对于特定的语言Fingerprint Analyzer
):可创建可用于重复检测的指纹。可以点击查看内置的分析器以及其示例
字符过滤器用于预处理字符流,然后再将其传递给令牌生成器。
字符过滤器将原始文本作为字符流接收,并且可以通过添加,删除或更改字符来转换流。例如,可以使用字符过滤器将印度阿拉伯数字(٠ ١٢٣٤٥٦٧٨ ٩)转换为其等效的阿拉伯语-拉丁语(0123456789),或从流中剥离HTML元素。
Elasticsearch有许多内置的字符过滤器,可用于构建 自定义分析器。
html_strip
字符过滤带出HTML元素,比如像和解码HTML实体&。mapping
字符过滤器替换指定更换指定的字符串中的任何事件。pattern_replace
字符过滤器将所有与正则表达式匹配的字符替换为指定的替换。可以点击查看内置的字符过滤器以及其示例