ElasticSearch应用篇-搜索增强

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: ES有一些非常强大的能力,例如:根据用户搜索的时候,也可以搜索同义词,也可以基于语义进行分词,返回最最适合的结果,ElasticSearch是如何实现这种能力的呢?

一、ES搜索与Analyzer

1.ES搜索过程

为了搞清楚这个问题,我们需要提前搞清楚ES搜索的过程,ElasticSearch的这个能力是由Analyzer来实现的。ES中一个Analyzer处理搜索的过程如下:
ElasticSearch应用篇-搜索增强-搜索流程.png

从这个处理流程可以看到,在token filter会为词条增加一些同义词,这就是ES可以支持同义词搜索的原因所在。

2.Analyzer(解析器)

1)Analyzer组成

Analyzer由0个或多个char_filter,1个tokenizer,0个或多个token filter组成。

char_filter用于分词前对原搜索的句子进行处理,如去除HTML标签。

tokenizer用于将搜索的句子分成多个词组,如将一段话根据分词器或者空格拆分成多个词等。

token filter用于处理tokenizer输出的词组,常见的操作有:删除、修改增加某些词,例如:去掉a、the词组,大写转小写,增加同义词。

Analyzer的配置说明:

处理器 描述
tokenizer 通用的或者注册的tokenizer.
filter 通用的或者注册的 token filters.
char_filter 通用的或者注册的 character filters.
position_increment_gap 距离查询时,最大允许查询的距离,默认是100

2)Analyzer与search_analyzer的区别

ES中主要有两种情况会用分析器:一是插入文档时,将text类型的字段做分词然后插入倒排索引,二是查询时,先对要查询的text类型的输入做分词,再去倒排索引搜索。使用的具体规则是:创建索引时,只看字段有没有定义analyzer,有定义的话就用定义的,没定义就用ES预设的;在查询时,先看字段有没有定义search_analyzer,如果没有定义,去看有没有analyzer,再没有定义才会去使用ES预设的。

2.CharFilter

elasticearch只提供了三种字符过滤器:

1)HTML Strip Char Filter(HTML字符过滤器)

可以去除HTML标签,例如将

I'
Love cat

转变为:I Love cat。

示例代码:

{
    "tokenizer":"keyword",

    "char_filter":[

        "html_strip"

    ],

    "text":"<p>I' <br>Love</br> cat</p>"
}

结果为:

{
    "tokenizer":"keyword",

    "char_filter":[

        "html_strip"

    ],

    "text":"I Love cat"
}

2)Mapping Char Filter(映射字符过滤器)

可以替换查询字符串的内容,例如将“特朗普”转变为:TTT。

{
    "settings":{

        "analysis":{

            "analyzer":{

                "my_analyzer":{

                    "tokenizer":"keyword",

                    "char_filter":[

                        "my_char_filter"

                    ]

                }

            },

            "char_filter":{

                "my_char_filter":{

                    "type":"mapping",

                    "mappings":[

                        "特朗普=> TTT "

                    ]

                }

            }

        }

    }
}

创建索引或者搜索的时候将会将“特朗普”转换成“TTT”。

3)Pattern Replace Char Filter(模式替换过滤器)

可以使用正则表达式匹配并替换字符串中的字符。具体能力看正则表达式,具体示例省略。

3.tokenizer

接下来介绍几种常见的分词器。

1)standard tokenizer (标准分词器)

标准类型的tokenizer,对英语等欧洲语言非常友好,支持Unicode。属性:

属性 说明
max_token_length 最大的token集合,即经过tokenizer过后得到的结果集的最大值。如果token的长度超过了设置的长度,将会继续分,默认255

2)NGram Tokenizer(连词分词器)

如果词的长度大于最短词长度则分词,依次分成最小长度递进到最大长度的词。例如:min_gram=2, max_gram=3下王者荣耀的分词结果为:王者、王者荣、者荣耀、荣耀。

属性:

设置 说明 Default value
min_gram 分词后词语的最小长度 1
max_gram 分词后词语的最大长度 2
token_chars 设置分词的形式 [](Keep all characters)letter(单词),digit(数字),whitespace(空白),punctuation(标点,如!),symbol(符号,如&)

3)Edge NGram tokenizer(自动补全)

和NGramTokenizer非常相似,不过支持自动补全功能。

二、中文分词

1.场景

假设ik_demo索引中有以下记录,如下表格所示

_index _type _id _score message
ik_demo _doc 1 1 我爱中华人民共和国
ik_demo _doc 2 1 我来自中国湖北枣阳

按照这个示例,“国”在不同上下文中是不同的,第二句“中国”是一个词,单独搜索“国”的时候应该返回此记录。

2.elasticsearch-analysis-ik

elasticsearch需要先安装分词器才能支持分词功能,这里使用的是elasticsearch-analysis-ik,地址:https://github.com/medcl/elasticsearch-analysis-ik

安装ik:

./bin/elasticsearch-plugin installhttps://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.3.2/elasticsearch-analysis-ik-7.3.2.zip

注意:7.3.2为使用的elasticsearch版本;

3.设置mapping

curl -XPUT 'http://localhost:9200/ik_demo/_mapping?pretty' -H 'Content-Type: application/json' -d '
{
    "properties" : {

        "message" : {

            "type" : "text",

            "analyzer" : "ik_max_word",

            "search_analyzer" : "ik_smart",

            "fields" : {

              "keyword" : {

                "type" : "keyword",

                "ignore_above" : 256

              }

            }

        }

    }
}'

4.添加数据

curl -XPUT 'http://localhost:9200/ik_demo/_doc/1?pretty' -H 'Content-Type: application/json' -d '
{ "message": "我爱中华人民共和国"}'

curl -XPUT 'http://localhost:9200/ik_demo/_doc/2?pretty' -H 'Content-Type: application/json' -d '
{"message": "我来自中国湖北枣阳"}'

5.搜索

分词过程中会将中国作为一个词,所以单独搜索“国”的时候,将无法搜索到带有“我来自中国湖北枣阳”这个记录。

curl -XGET 'http://localhost:9200/ik_demo/_search?pretty=true' -H 'Content-Type: application/json' -d '
{"query":{"match":{"message":"国"}}}'

返回结果:

{
    "took":3,

    "timed_out":false,

    "_shards":{

        "total":5,

        "successful":5,

        "skipped":0,

        "failed":0

    },

    "hits":{

        "total":{

            "value":1,

            "relation":"eq"

        },

        "max_score":0.2876821,

        "hits":[

            {

                "_index":"ik_demo",

                "_type":"_doc",

                "_id":"1",

                "_score":0.2876821,

                "_source":{

                    "message":"我爱中华人民共和国"

                }

            }

        ]

    }
}

这里仅简单介绍使用,具体分词内容可以参考:https://github.com/medcl/elasticsearch-analysis-ik

三、近义词、同义词搜索

1.场景

假设synonym_demo索引中有以下记录,如下表格所示

_index _type _id _score message
synonym_demo _doc 1 1 我喜欢猫
synonym_demo _doc 2 1 我喜欢cat
synonym_demo _doc 3 1 我喜欢狗

猫和cat其实是同一个意思,如果想搜索猫的时候,将【1、2】记录都搜索出来,应该如何处理呢?

2.elasticsearch-dynamic-synonym

安装同义词插件,这里使用的是elasticsearch-dynamic-synonym,地址:https://github.com/ginobefun/elasticsearch-dynamic-synonym

安装:

git clone https://github.com/ginobefun/elasticsearch-dynamic-synonym.git

mvn clean install -DskipTests

将target/releases/elasticsearch-dynamic-synonym-.zip解压到ES_HOME/plugin/dynamic-synonym目录中。

修改plugin-descriptor.properties,注释掉site、jvm、isolated,并且将elasticsearch.version改成elasticsearch的版本。如下所示:

site=${elasticsearch.plugin.site}

jvm=true

isolated=${elasticsearch.plugin.isolated}

elasticsearch.version=7.3.2

3.创建索引

在ES_HOME/config/analysis/synonyms.txt中添加同义词:猫,cat

创建索引:

curl -XPUT 'http://localhost:9200/synonym_demo?pretty' -H 'Content-Type: application/json' -d '
  {
  "settings": {

      "analysis": {

        "analyzer": {

          "my_dynamic_synonym": {

            "type": "custom",

            "tokenizer": "whitespace",

            "filter": ["my_synonym"]

          }

        },

        "filter": {

          "my_synonym" : {

                  "type" : "synonym",

                  "expand": true,

                  "ignore_case": true,

                  "synonyms_path" : "analysis/synonyms.txt"

          }

        }

      }

  },

  "mappings":{

      "properties" : {

          "message" : {

              "type" : "text",

              "analyzer" : "ik_max_word",

              "search_analyzer" : "my_dynamic_synonym",

              "fields" : {

                "keyword" : {

                  "type" : "keyword",

                  "ignore_above" : 256

                }

              }

          }

      }

  }
  }'

4.添加数据

curl -XPUT 'http://localhost:9200/synonym_demo/_doc/1?pretty' -H 'Content-Type: application/json' -d '{ "message": "我喜欢猫" }'
curl -XPUT 'http://localhost:9200/synonym_demo/_doc/2?pretty' -H 'Content-Type: application/json' -d '{  "message": "我喜欢cat" }'
curl -XPUT 'http://localhost:9200/synonym_demo/_doc/3?pretty' -H 'Content-Type: application/json' -d '{ "message": "我喜欢狗"}'

5.搜索

因为猫、cat是同义词,所以搜索cat的时候,猫也应该会返回。

curl -XGET 'http://localhost:9200/synonym_demo/_search?pretty=true' -H 'Content-Type: application/json' -d '
{"query":{"match":{"message":"cat"}}}'

返回结果:

{
    "took" : 3,

    "timed_out" : false,

    "_shards" : {

        "total" : 1,

        "successful" : 1,

        "skipped" : 0,

        "failed" : 0

    },

    "hits" : {

        "total" : {

            "value" : 2,

            "relation" : "eq"

        },

        "max_score" : 1.2039728,

        "hits" : [

            {

                "_index" : "synonym_demo",

                "_type" : "_doc",

                "_id" : "1",

                "_score" : 1.2039728,

                "_source" : {

                    "message" : "我喜欢猫"

                }

            },

            {

                "_index" : "synonym_demo",

                "_type" : "_doc",

                "_id" : "2",

                "_score" : 1.2039728,

                "_source" : {

                    "message" : "我喜欢cat"

                }

            }

        ]

    }
}

四、参考文档

search_analyzer:

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-analyzer.html

Custom Analyzer:

https://www.elastic.co/guide/en/elasticsearch/reference/2.1/analysis-custom-analyzer.html

elasticsearch-dynamic-synonym:

https://github.com/ginobefun/elasticsearch-dynamic-synonym

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
1月前
|
存储 自然语言处理 BI
|
3月前
|
SQL JSON 大数据
ElasticSearch的简单介绍与使用【进阶检索】 实时搜索 | 分布式搜索 | 全文搜索 | 大数据处理 | 搜索过滤 | 搜索排序
这篇文章是Elasticsearch的进阶使用指南,涵盖了Search API的两种检索方式、Query DSL的基本语法和多种查询示例,包括全文检索、短语匹配、多字段匹配、复合查询、结果过滤、聚合操作以及Mapping的概念和操作,还讨论了Elasticsearch 7.x和8.x版本中type概念的变更和数据迁移的方法。
ElasticSearch的简单介绍与使用【进阶检索】 实时搜索 | 分布式搜索 | 全文搜索 | 大数据处理 | 搜索过滤 | 搜索排序
|
2月前
|
机器学习/深度学习 存储 监控
Elasticsearch 在日志分析中的应用
【9月更文第2天】随着数字化转型的推进,日志数据的重要性日益凸显。日志不仅记录了系统的运行状态,还提供了宝贵的洞察,帮助企业改进产品质量、优化用户体验以及加强安全防护。Elasticsearch 作为一个分布式搜索和分析引擎,因其出色的性能和灵活性,成为了日志分析领域的首选工具之一。本文将探讨如何使用 Elasticsearch 作为日志分析平台的核心组件,并详细介绍 ELK(Elasticsearch, Logstash, Kibana)栈的搭建和配置流程。
283 4
|
17天前
|
存储 SQL 监控
|
16天前
|
存储 缓存 固态存储
Elasticsearch高性能搜索
【11月更文挑战第1天】
32 6
|
17天前
|
自然语言处理 监控 数据可视化
|
14天前
|
API 索引
Elasticsearch实时搜索
【11月更文挑战第2天】
30 1
|
1月前
|
人工智能
云端问道12期-构建基于Elasticsearch的企业级AI搜索应用陪跑班获奖名单公布啦!
云端问道12期-构建基于Elasticsearch的企业级AI搜索应用陪跑班获奖名单公布啦!
172 2
|
1月前
|
Web App开发 JavaScript Java
elasticsearch学习五:springboot整合 rest 操作elasticsearch的 实际案例操作,编写搜索的前后端,爬取京东数据到elasticsearch中。
这篇文章是关于如何使用Spring Boot整合Elasticsearch,并通过REST客户端操作Elasticsearch,实现一个简单的搜索前后端,以及如何爬取京东数据到Elasticsearch的案例教程。
188 0
elasticsearch学习五:springboot整合 rest 操作elasticsearch的 实际案例操作,编写搜索的前后端,爬取京东数据到elasticsearch中。
|
4月前
|
存储 人工智能 自然语言处理
阿里云Elasticsearch AI场景语义搜索最佳实践
本文介绍了如何使用阿里云Elasticsearch结合搜索开发工作台搭建AI语义搜索。
17300 68
下一篇
无影云桌面