ElasticSearch【有与无】【搜索引擎】【ES17】处理各种语言【选读】

目录

1.简介

1.1.使用语言分析器

1.2.配置语言分析器

1.3.混合语言的陷阱

在索引的时候

在搜索的时候

1.4.每份文档一种语言

外语单词

1.5.每个域一种语言

1.6.混合语言域

切分到不同的域

进行多次分析

使用 n-grams


1.简介

Elasticsearch 为很多世界流行语言提供良好的、简单的、开箱即用的语言分析器集合:

阿拉伯语、亚美尼亚语、巴斯克语、巴西语、保加利亚语、加泰罗尼亚语、中文、捷克语、丹麦、荷兰语、英语、芬兰语、法语、加里西亚语、德语、希腊语、北印度语、匈牙利语、印度尼西亚、爱尔兰语、意大利语、日语、韩国语、库尔德语、挪威语、波斯语、葡萄牙语、罗马尼亚语、俄语、西班牙语、瑞典语、土耳其语和泰语。

 

这些分析器承担以下四种角色:

  1. 文本拆分为单词:he quick brown foxes → [ Thequickbrownfoxes]
  2. 大写转小写:The → the
  3. 移除常用的 停用词:[ Thequickbrownfoxes] → [ quickbrownfoxes]
  4. 将变型词(例如复数词,过去式)转化为词根:foxes → fox
  5. 英语 分析器移除了所有格 'sJohn’s → john
  6. 法语 分析器移除了 元音省略 例如 l' 和 qu' 和 变音符号 例如 ¨ 或 ^ :l'église → eglis
  7.  分析器规范化了切词, 将切词中的 ä 和 ae 替换为 a , 或将 ß 替换为 ss :äußerst → ausserst

 

1.1.使用语言分析器

Elasticsearch 的内置分析器都是全局可用的,不需要提前配置,它们也可以在字段映射中直接指定在某字段上

【举例】

PUT /my_index
{
  "mappings": {
    "blog": {
      "properties": {
        "title": {
          "type":     "string",
          "analyzer": "english"  // title 字段将会用 english(英语)分析器替换默认的 standard(标准)分析器
        }
      }
    }
  }
}

【分析】

GET /my_index/_analyze?field=title 
I'm not happy about the foxes

切词为: I'm ,happy, about, fox

降低了精准匹配文档的能力

【优化】

PUT /my_index
{
  "mappings": {
    "blog": {
      "properties": {
        "title": { // 主 title 字段使用 standard(标准)分析器。
          "type": "string",
          "fields": {
            "english": {  // title.english 子字段使用 english(英语)分析器。
              "type":     "string",
              "analyzer": "english"
            }
          }
        }
      }
    }
  }
}

【测试】

PUT /my_index/blog/1
{ "title": "I'm happy for this fox" }

PUT /my_index/blog/2
{ "title": "I'm not happy about my fox problem" }

GET /_search
{
  "query": {
    "multi_match": {
      "type":     "most_fields", 
      "query":    "not happy foxes",
      "fields": [ "title", "title.english" ]
    }
  }
}

感谢 title.english 字段的切词,无论文档中是否含有单词 foxes 都会被搜索到,第二份文档的相关性排行要比第一份高, 因为在 title 字段中匹配到了单词 not 。

 

1.2.配置语言分析器

语言分析器都不需要任何配置,开箱即用, 它们中的大多数都允许你控制它们的各方面行为,具体来说:

  • 词干提取排除
  • 自定义停用词

【举例】

PUT /my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_english": {
          "type": "english",
          "stem_exclusion": [ "organization", "organizations" ], // 防止 organization 和 organizations 被缩减为词干
          "stopwords": [  // 指定一个自定义停用词列表
            "a", "an", "and", "are", "as", "at", "be", "but", "by", "for",
            "if", "in", "into", "is", "it", "of", "on", "or", "such", "that",
            "the", "their", "then", "there", "these", "they", "this", "to",
            "was", "will", "with"
          ]
        }
      }
    }
  }
}
GET /my_index/_analyze?analyzer=my_english 
The World Health Organization does not sell organs

切词为 world 、 health 、 organization 、 does 、 not 、 sell 、 organ

 

1.3.混合语言的陷阱

在索引的时候

多语言文档主要有以下三个类型:

  • 一种是每份 document (文档)有自己的主语言,并包含一些其他语言的片段
  • 一种是每个 field (域)有自己的主语言, 并包含一些其他语言的片段
  • 一种是每个 field (域)都是混合语言

(分词)目标不总是可以实现,我们应当保持将不同语言分隔开。在同一份倒排索引内混合多种语言可能造成一些问题。

不合理的词干提取

德语的词干提取规则跟英语,法语,瑞典语等是不一样的。 为不同的语言提供同样的词干提规则 将会导致有的词的词根找的正确,有的词的词根找的不正确,有的词根本找不到词根。 甚至是将不同语言的不同含义的词切为同一个词根,合并这些词根的搜索结果会给用户带来困恼。

每种书写方式一种词干提取器

只有一种情况, only-one-stemmer(唯一词干提取器)会发生,就是每种语言都有自己的书写方式。
例如,在以色列就有很大的可能一个文档包含希伯来语, 阿拉伯语,俄语(古代斯拉夫语),和英语。

אזהרה - Предупреждение - تحذير - Warning

每种语言使用不同的书写方式,所以一种语言的词干提取器就不会干扰其他语言的,允许为同一份文本提供多种词干提取器。

不正确的倒排文档频率

一个 term (词)在一份文档中出现的频率越高,该term(词)的权重就越低。 为了精确的计算相关性,你需要精确的统计 term-frequency (词频)。

一段德文出现在英语为主的文本中会给与德语单词更高的权重,给那么高权重是因为德语单词相对来说更稀有。 但是如果这份文档跟以德语为主的文档混合在一起,那么这段德文就会有很低的权重。

 

在搜索的时候

通常你能从用户选择的语言界面来确定用户的主语言,(例如, mysite.de 和 mysite.fr ) 或者从用户的浏览器的HTTP header(HTTP头文件) accept-language 确定。

用户的搜索也注意有三个方面:

  • 用户使用他的主语言搜索。
  • 用户使用其他的语言搜索,但希望获取主语言的搜索结果。
  • 用户使用其他语言搜索,并希望获取该语言的搜索结果。(例如,精通双语的人,或者网络咖啡馆的外国访问者)。

通常来说,给与用户语言偏好的搜索很有意义。

 

语言识别

确定用户搜索请求的语言并不是那么简单。

详细内容是来自 Mike McCandless 的 chromium-compact-language-detector 工具包,使用的是google开发的基于 (Apache License 2.0)的开源工具包 Compact Language Detector (CLD) 。 它小巧,快速,且精确,并能根据短短的两句话就可以检测 160+ 的语言。 它甚至能对单块文本检测多种语言。支持多种开发语言包括 Python,Perl,JavaScript,PHP,C#/.NET,和 R 。

 

1.4.每份文档一种语言

【举例】

PUT /blogs-en
{
  "mappings": {
    "post": {
      "properties": {
        "title": {
          "type": "string", 
          "fields": {
            "stemmed": {
              "type":     "string",
              "analyzer": "english
            }
}}}}}}

PUT /blogs-fr
{
  "mappings": {
    "post": {
      "properties": {
        "title": {
          "type": "string", 
          "fields": {
            "stemmed": {
              "type":     "string",
              "analyzer": "french
            }
}}}}}}

----------------------------------------------------------

这个查询会在所有以 blogs- 开头的索引中执行

GET /blogs-*/post/_search 
{
    "query": {
        "multi_match": {
            "query":   "deja vu",
            "fields":  [ "title", "title.stemmed" ]  // title.stemmed 字段使用每个索引中指定的分析器查询
            "type":    "most_fields"
        }
    },
    "indices_boost": { // 每个索引的结果添加权重。任何其他语言会有一个中性的权重 1 。
        "blogs-en": 3,
        "blogs-fr": 2
    }

}

 

外语单词

当然,有些文档含有一些其他语言的单词或句子,且不幸的是这些单词被切为了正确的词根。对于主语言文档,这通常并不是主要的问题。用户经常需要搜索很精确的单词--例如,一个其他语言的引用--而不是语型变化过的单词。

不要对语言使用类型
你也许很倾向于为每个语言使用分开的类型,来代替使用分开的索引。 为了达到最佳效果,你应当避免使用类型。
在 [mapping] 中,不同类型但有相同域名的域会被索引在 相同的倒排索引 中。这意味着不同类型(和不同语言)的词频混合在了一起。

为了确保一种语言的词频不会污染其他语言的词频,无论是为每个语言使用单独的索引,还是使用单独的域都可以。

 

1.5.每个域一种语言

PUT /movies
{
  "mappings": {
    "movie": {
      "properties": {
        "title": { // 使用 standard (标准)分析器。
          "type":       "string"
        },
        "title_br": { 
            "type":     "string",
            "analyzer": "brazilian"
        },
        "title_cz": { 
            "type":     "string",
            "analyzer": "czech"
        },
        "title_en": { 
            "type":     "string",
            "analyzer": "english"
        },
        "title_es": { 
            "type":     "string",
            "analyzer": "spanish"
        }
      }
    }
  }
}

文档的一种语言可以单独查询,也可以通过查询多个域来查询多种语言。我们甚至可以通过对特定语言设置偏好来提高字段优先级

GET /movies/movie/_search
{
    "query": {
        "multi_match": {
            "query":    "club de la lucha",
            "fields": [ "title*", "title_es^2" ],  // 搜索查询所有以 title 为前缀的域,但是对 title_es 域加权重 2 。其他的所有域是中性权重 1 
            "type":     "most_fields"
        }
    }
}

 

1.6.混合语言域

{ "body": "Page not found / Seite nicht gefunden / Page non trouvée" }

假设你的混合语言使用的是一样的脚本,例如拉丁文,你有三个可用的选择:

  • 切分到不同的域
  • 进行多次分析
  • 使用 n-grams

 

切分到不同的域

 每个域一种语言

 

进行多次分析

PUT /movies
{

 "settings": { "analysis": {...} },// 使用 n-grams
  "mappings": {
    "title": {
      "properties": {
        "title": { // 使用 standard (标准)分析器
          "type": "string",
          "fields": {
            "de": { 
              "type":     "string",
              "analyzer": "german"
            },
            "en": { 
              "type":     "string",
              "analyzer": "english"
            },
            "fr": { 
              "type":     "string",
              "analyzer": "french"
            },
            "es": { 
              "type":     "string",
              "analyzer": "spanish"
            }
          }
        }
      }
    }
  }
}

使用 n-grams

如上。参考n-grams

GET /movies/movie/_search
{
    "query": {
        "multi_match": {
            "query":    "club de la lucha",
            "fields": [ "title*^1.5", "title.general" ], 
            "type":     "most_fields",
            "minimum_should_match": "75%" 
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

琴 韵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值