边缘 n-gram 分词器编辑

edge_ngram 分词器首先在遇到指定字符列表中的一个字符时将文本分解为单词,然后为每个单词生成 N-gram,其中 N-gram 的开头锚定在单词的开头。

边缘 N-Gram 对于*边输入边搜索*查询非常有用。

如果您需要对具有广为人知的顺序的文本(例如电影或歌曲标题)进行*边输入边搜索*,则 自动完成建议器 是比边缘 N-gram 更高效的选择。当尝试自动完成可以按任何顺序出现的单词时,边缘 N-gram 具有优势。

示例输出编辑

使用默认设置,edge_ngram 分词器将初始文本视为单个标记,并生成最小长度为 1 且最大长度为 2 的 N-gram

response = client.indices.analyze(
  body: {
    tokenizer: 'edge_ngram',
    text: 'Quick Fox'
  }
)
puts response
POST _analyze
{
  "tokenizer": "edge_ngram",
  "text": "Quick Fox"
}

上面的句子将生成以下词条

[ Q, Qu ]

这些默认的 gram 长度几乎完全没用。您需要在使用 edge_ngram 之前对其进行配置。

配置编辑

edge_ngram 分词器接受以下参数

min_gram
gram 中的最小字符长度。默认为 1
max_gram

gram 中的最大字符长度。默认为 2

请参阅 max_gram 参数的限制

token_chars

应包含在标记中的字符类。Elasticsearch 将在不属于指定类的字符处进行拆分。默认为 [](保留所有字符)。

字符类可以是以下任意一种

  • letter —  例如 abï
  • digit —  例如 37
  • whitespace —  例如 " ""\n"
  • punctuation — 例如 !"
  • symbol —  例如 $
  • custom —  需要使用 custom_token_chars 设置设置的自定义字符。
custom_token_chars
应被视为标记一部分的自定义字符。例如,将其设置为 +-_ 将使分词器将加号、减号和下划线视为标记的一部分。

max_gram 参数的限制编辑

edge_ngram 分词器的 max_gram 值限制了标记的字符长度。当 edge_ngram 分词器与索引分析器一起使用时,这意味着长度超过 max_gram 长度的搜索词可能与任何索引词条都不匹配。

例如,如果 max_gram3,则搜索 apple 将不会匹配索引词条 app

为了解决这个问题,您可以将 truncate 标记过滤器与搜索分析器一起使用,以将搜索词缩短为 max_gram 字符长度。但是,这可能会返回不相关的结果。

例如,如果 max_gram3 并且搜索词被截断为三个字符,则搜索词 apple 将被缩短为 app。这意味着搜索 apple 将返回与 app 匹配的任何索引词条,例如 applyapproximateapple

我们建议您测试这两种方法,以确定哪种方法最适合您的用例和所需的搜索体验。

示例配置编辑

在本例中,我们将 edge_ngram 分词器配置为将字母和数字视为标记,并生成最小长度为 2 且最大长度为 10 的 gram

response = client.indices.create(
  index: 'my-index-000001',
  body: {
    settings: {
      analysis: {
        analyzer: {
          my_analyzer: {
            tokenizer: 'my_tokenizer'
          }
        },
        tokenizer: {
          my_tokenizer: {
            type: 'edge_ngram',
            min_gram: 2,
            max_gram: 10,
            token_chars: [
              'letter',
              'digit'
            ]
          }
        }
      }
    }
  }
)
puts response

response = client.indices.analyze(
  index: 'my-index-000001',
  body: {
    analyzer: 'my_analyzer',
    text: '2 Quick Foxes.'
  }
)
puts response
PUT my-index-000001
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "edge_ngram",
          "min_gram": 2,
          "max_gram": 10,
          "token_chars": [
            "letter",
            "digit"
          ]
        }
      }
    }
  }
}

POST my-index-000001/_analyze
{
  "analyzer": "my_analyzer",
  "text": "2 Quick Foxes."
}

上面的例子会生成以下词条

[ Qu, Qui, Quic, Quick, Fo, Fox, Foxe, Foxes ]

通常我们建议在索引时和搜索时使用相同的 analyzer。对于 edge_ngram 分词器,建议有所不同。只有在索引时使用 edge_ngram 分词器才有意义,以确保部分单词可用于在索引中进行匹配。在搜索时,只需搜索用户输入的词条,例如:Quick Fo

下面是如何为*边输入边搜索*设置字段的示例。

请注意,索引分析器的 max_gram 值为 10,这会将索引词条限制为 10 个字符。搜索词不会被截断,这意味着长度超过 10 个字符的搜索词可能与任何索引词条都不匹配。

response = client.indices.create(
  index: 'my-index-000001',
  body: {
    settings: {
      analysis: {
        analyzer: {
          autocomplete: {
            tokenizer: 'autocomplete',
            filter: [
              'lowercase'
            ]
          },
          autocomplete_search: {
            tokenizer: 'lowercase'
          }
        },
        tokenizer: {
          autocomplete: {
            type: 'edge_ngram',
            min_gram: 2,
            max_gram: 10,
            token_chars: [
              'letter'
            ]
          }
        }
      }
    },
    mappings: {
      properties: {
        title: {
          type: 'text',
          analyzer: 'autocomplete',
          search_analyzer: 'autocomplete_search'
        }
      }
    }
  }
)
puts response

response = client.index(
  index: 'my-index-000001',
  id: 1,
  body: {
    title: 'Quick Foxes'
  }
)
puts response

response = client.indices.refresh(
  index: 'my-index-000001'
)
puts response

response = client.search(
  index: 'my-index-000001',
  body: {
    query: {
      match: {
        title: {
          query: 'Quick Fo',
          operator: 'and'
        }
      }
    }
  }
)
puts response
PUT my-index-000001
{
  "settings": {
    "analysis": {
      "analyzer": {
        "autocomplete": {
          "tokenizer": "autocomplete",
          "filter": [
            "lowercase"
          ]
        },
        "autocomplete_search": {
          "tokenizer": "lowercase"
        }
      },
      "tokenizer": {
        "autocomplete": {
          "type": "edge_ngram",
          "min_gram": 2,
          "max_gram": 10,
          "token_chars": [
            "letter"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "autocomplete",
        "search_analyzer": "autocomplete_search"
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "title": "Quick Foxes" 
}

POST my-index-000001/_refresh

GET my-index-000001/_search
{
  "query": {
    "match": {
      "title": {
        "query": "Quick Fo", 
        "operator": "and"
      }
    }
  }
}

autocomplete 分析器会索引词条 [qu, qui, quic, quick, fo, fox, foxe, foxes]

autocomplete_search 分析器会搜索词条 [quick, fo],这两个词条都出现在索引中。