混合语言域

通常,那些从源数据中获得的多种语言混合在一个域中的文档会超出你的控制,例如从网上爬取的页面:

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

正确的处理多语言类型文档是非常困难的。即使你简单对所有的域使用 standard (标准)分析器, 但你的文档会变得不利于搜索,除非你使用了合适的词干提取器。当然,你不可能只选择一个词干提取器。 词干提取器是由语言具体决定的。或者,词干提取器是由语言和脚本所具体决定的。像在 different-scripts 讨论中那样。 如果每个语言都使用不同的脚本,那么词干提取器就可以合并了。

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

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

切分到不同的域

identifying-language 提到过的紧凑的语言检测可以告诉你哪部分文档属于哪种语言。你可以用 one-lang-fields 中用过的一样的方法来根据语言切分文本。

进行多次分析

如果你主要处理数量有限的语言,你可以使用多个域,每种语言都分析文本一次。

  1. PUT /movies
  2. {
  3. "mappings": {
  4. "title": {
  5. "properties": {
  6. "title": { (1)
  7. "type": "string",
  8. "fields": {
  9. "de": { (2)
  10. "type": "string",
  11. "analyzer": "german"
  12. },
  13. "en": { (2)
  14. "type": "string",
  15. "analyzer": "english"
  16. },
  17. "fr": { (2)
  18. "type": "string",
  19. "analyzer": "french"
  20. },
  21. "es": { (2)
  22. "type": "string",
  23. "analyzer": "spanish"
  24. }
  25. }
  26. }
  27. }
  28. }
  29. }
  30. }

<1> 主域 title 使用 standard (标准)分析器

<2> 每个子域提供不同的语言分析器来对 title 域文本进行分析。

使用 n-grams

你可以使用 ngrams-compound-words 中描述的方法索引所有的词汇为 n-grams。大多数语型变化包含给单词添加一个后缀(或在一些语言中添加前缀),所以通过将单词拆成 n-grams,你有很大的机会匹配到相似但不完全一样的单词。这个可以结合 analyze-multiple times (多次分析)方法为不支持的语言提供全域抓取:

  1. PUT /movies
  2. {
  3. "settings": {
  4. "analysis": {...} (1)
  5. },
  6. "mappings": {
  7. "title": {
  8. "properties": {
  9. "title": {
  10. "type": "string",
  11. "fields": {
  12. "de": {
  13. "type": "string",
  14. "analyzer": "german"
  15. },
  16. "en": {
  17. "type": "string",
  18. "analyzer": "english"
  19. },
  20. "fr": {
  21. "type": "string",
  22. "analyzer": "french"
  23. },
  24. "es": {
  25. "type": "string",
  26. "analyzer": "spanish"
  27. },
  28. "general": { (2)
  29. "type": "string",
  30. "analyzer": "trigrams"
  31. }
  32. }
  33. }
  34. }
  35. }
  36. }
  37. }

<1> 在 analysis 章节, 我们按照 ngrams-compound-words 中描述的定义了同样的 trigrams 分析器。

<2> 在 title.general 域使用 trigrams 分析器索引所有的语言。

当查询抓取所有 general 域时,你可以使用minimum_should_match (最少应当匹配数)来减少低质量的匹配。或许也需要对其他字段进行稍微的加权,给与主语言域的权重要高于其他的在 general 上的域:

  1. GET /movies/movie/_search
  2. {
  3. "query": {
  4. "multi_match": {
  5. "query": "club de la lucha",
  6. "fields": [ "title*^1.5", "title.general" ], (1)
  7. "type": "most_fields",
  8. "minimum_should_match": "75%" (2)
  9. }
  10. }
  11. }

<1> 所有 titletitle.* 域给与了比 title.general 域稍微高的加权。

<2> minimum_should_match(最少应当匹配数) 参数减少了低质量匹配的返回数, 这对 title.general 域尤其重要。