本篇文章主要讲解中文分词和 ElasticSearch 中的重要 API —— Suggester,同时也会提到 Search Template、Index Alias 和 Function Score Query 等高级搜索功能。
当处理人类自然语言时,有时尽管搜索和原文不完全匹配,但是希望搜到一些内容。
可以采取的措施:
不同的索引使用不同的语言;同一个索引中,不同的字段使用不同的语言;一个文档的一个字段内混合不同的语言。
由于生产环境中最常见的中文分词器为 IK,因此本篇也以 IK 为主。
安装
仓库地址:L2ncE/es101
克隆仓库后进入到 docker-compose 文件 目录,将 docker.elastic.co/elasticsearch/elasticsearch:7.8.0
改为 zingimmick/elasticsearch-ik:7.8.0
。运行 docker-compose up
。
示例
POST _analyze
{
"analyzer": "ik_smart",
"text": ["剑桥分析公司多位高管对卧底记者说,他们确保了唐纳德·特朗普在总统大选中获胜"]
}
用于解耦程序和搜索 DSL。
示例
POST _scripts/tmdb
{
"script": {
"lang": "mustache",
"source": {
"_source": [
"title",
"overview"
],
"size": 20,
"query": {
"multi_match": {
"query": "{{q}}",
"fields": [
"title",
"overview"
]
}
}
}
}
}
POST tmdb/_search/template
{
"id":"tmdb",
"params": {
"q": "basketball with cartoon aliens"
}
}
上游可以不感知模版的变化,避免耦合。
实现零停机运维。比如在进行索引重建、版本升级、滚动更新等操作时,无需中断服务。
示例
1、插入数据
PUT movies-2019/_doc/1
{
"name":"the matrix",
"rating":5
}
PUT movies-2019/_doc/2
{
"name":"Speed",
"rating":3
}
2、设置别名
POST _aliases
{
"actions": [
{
"add": {
"index": "movies-2019",
"alias": "movies-latest"
}
}
]
}
POST movies-latest/_search
{
"query": {
"match_all": {}
}
}
可以在查询结束后对每一个匹配的文档进行一系列的重新算分,根据新生成的分数进行排序。
\_score
,例如将「热度」和「点赞数」作为算分的参考因素。示例
1、插入数据
DELETE blogs
PUT /blogs/_doc/1
{
"title": "About popularity",
"content": "In this post we will talk about...",
"votes": 0
}
PUT /blogs/_doc/2
{
"title": "About popularity",
"content": "In this post we will talk about...",
"votes": 100
}
PUT /blogs/_doc/3
{
"title": "About popularity",
"content": "In this post we will talk about...",
"votes": 1000000
}
2、使用多个参数测试
POST /blogs/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "popularity",
"fields": [ "title", "content" ]
}
},
"field_value_factor": {
"field": "votes",
"modifier": "log1p" ,
"factor": 0.1
}
}
}
}
3、一致性随机函数
POST /blogs/_search
{
"query": {
"function_score": {
"random_score": {
"seed": 911119
}
}
}
}
4、Boost Mode 和 Max Boost
POST /blogs/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "popularity",
"fields": [ "title", "content" ]
}
},
"field_value_factor": {
"field": "votes",
"modifier": "log1p" ,
"factor": 0.1
},
"boost_mode": "sum",
"max_boost": 3
}
}
}
Max Boost 可以将算分控制在一个最大值。Boost Mode 用于进行算分的数学运算。
实现搜索引擎中纠错的功能。原理是将文本分解为 Token 然后在索引的字典中查找相似的 Term 并返回。
四种 Suggester 的不同之处:
Suggester 类型 | 功能与特点 | 适用场景 |
---|---|---|
Term Suggester | 对输入文本的每个词条进行纠错或建议,基于索引中的词典查找相似 Term。 | 单个词条级别的纠错和建议(如拼写错误修正)。 |
Phrase Suggester | 在 Term Suggester 基础上,考虑多个词条之间的关系(如是否共同出现、相邻程度等)。 | 多个词组成的短语级别的纠错和建议(如句子片段的修正)。 |
Completion Suggester | 提供前缀匹配的自动补全功能,支持快速搜索建议(如用户输入时的提示)。 | 快速自动补全(如搜索框输入提示)。 |
Context Suggester | 基于 Completion Suggester,增加了上下文信息的支持(如地理位置、类别等过滤条件)。 | 需要结合上下文信息的自动补全(如特定分类下的搜索提示)。 |
示例
1、插入数据
DELETE articles
POST articles/_bulk
{ "index" : { } }
{ "body": "lucene is very cool"}
{ "index" : { } }
{ "body": "Elasticsearch builds on top of lucene"}
{ "index" : { } }
{ "body": "Elasticsearch rocks"}
{ "index" : { } }
{ "body": "elastic is the company behind ELK stack"}
{ "index" : { } }
{ "body": "Elk stack rocks"}
{ "index" : {} }
{ "body": "elasticsearch is rock solid"}
2、Term Suggester
几种 Suggestion Mode
POST /articles/_search
{
"size": 1,
"query": {
"match": {
"body": "lucen rock"
}
},
"suggest": {
"term-suggestion": {
"text": "lucen rock",
"term": {
"suggest_mode": "missing",
"field": "body"
}
}
}
}
3、Phrase Suggester
在 Term Suggester 的基础上增加了一些额外的逻辑。
POST /articles/_search
{
"suggest": {
"my-suggestion": {
"text": "lucne and elasticsear rock hello world ",
"phrase": {
"field": "body",
"max_errors":2,
"confidence":2,
"direct_generator":[{
"field":"body",
"suggest_mode":"always"
}],
"highlight": {
"pre_tag": "",
"post_tag": ""
}
}
}
}
}
4、Completion Suggester
提供了自动补全功能。对性能要求比较严苛,采用了非倒排索引的数据结构,将 Analyze 数据编码成 FST 和索引一起存放。FST 会整个加载进内存,速度很快。同时 FST 仅支持前缀查找。
DELETE articles
PUT articles
{
"mappings": {
"properties": {
"title_completion":{
"type": "completion"
}
}
}
}
POST articles/_bulk
{ "index" : { } }
{ "title_completion": "lucene is very cool"}
{ "index" : { } }
{ "title_completion": "Elasticsearch builds on top of lucene"}
{ "index" : { } }
{ "title_completion": "Elasticsearch rocks"}
{ "index" : { } }
{ "title_completion": "elastic is the company behind ELK stack"}
{ "index" : { } }
{ "title_completion": "Elk stack rocks"}
{ "index" : {} }
POST articles/_search?pretty
{
"size": 0,
"suggest": {
"article-suggester": {
"prefix": "elk ",
"completion": {
"field": "title_completion"
}
}
}
}
5、Context Suggester
是 Completion Suggester 的拓展,能够在搜索中加入更多的上下文信息。
可以定义两种类型的 Context:
实现 Context Suggester 的具体步骤:
DELETE comments
PUT comments
PUT comments/_mapping
{
"properties": {
"comment_autocomplete":{
"type": "completion",
"contexts":[{
"type":"category",
"name":"comment_category"
}]
}
}
}
POST comments/_doc
{
"comment":"I love the star war movies",
"comment_autocomplete":{
"input":["star wars"],
"contexts":{
"comment_category":"movies"
}
}
}
POST comments/_doc
{
"comment":"Where can I find a Starbucks",
"comment_autocomplete":{
"input":["starbucks"],
"contexts":{
"comment_category":"coffee"
}
}
}
POST comments/_search
{
"suggest": {
"MY_SUGGESTION": {
"prefix": "sta",
"completion":{
"field":"comment_autocomplete",
"contexts":{
"comment_category":"coffee"
}
}
}
}
}
这是该系列的第六篇,主要讲解中文分词和 ElasticSearch 中的重要 API —— Suggester,同时也提到 Search Template、Index Alias 和 Function Score Query 等高级搜索功能。可以自己去到 Kibana 的 Dev Tool 实战操作,未来会持续更新该系列,欢迎关注。
同时欢迎关注小红书:LanLance。不定时分享职场思考、大厂方法论和后端经验❤️