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可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
4月前
|
运维 监控 Java
探索Elasticsearch在Java环境下的全文检索应用实践
【6月更文挑战第30天】在大数据背景下,Elasticsearch作为分布式搜索分析引擎,因其扩展性和易用性备受青睐。本文指导在Java环境中集成Elasticsearch,涉及安装配置、使用RestHighLevelClient连接、索引与文档操作,如创建索引、插入文档及全文检索查询。此外,还讨论了高级查询、性能优化和故障排查,帮助开发者高效处理非结构化数据全文检索。
134 0
|
3天前
|
存储 自然语言处理 BI
|
2月前
|
SQL JSON 大数据
ElasticSearch的简单介绍与使用【进阶检索】 实时搜索 | 分布式搜索 | 全文搜索 | 大数据处理 | 搜索过滤 | 搜索排序
这篇文章是Elasticsearch的进阶使用指南,涵盖了Search API的两种检索方式、Query DSL的基本语法和多种查询示例,包括全文检索、短语匹配、多字段匹配、复合查询、结果过滤、聚合操作以及Mapping的概念和操作,还讨论了Elasticsearch 7.x和8.x版本中type概念的变更和数据迁移的方法。
ElasticSearch的简单介绍与使用【进阶检索】 实时搜索 | 分布式搜索 | 全文搜索 | 大数据处理 | 搜索过滤 | 搜索排序
|
1月前
|
机器学习/深度学习 存储 监控
Elasticsearch 在日志分析中的应用
【9月更文第2天】随着数字化转型的推进,日志数据的重要性日益凸显。日志不仅记录了系统的运行状态,还提供了宝贵的洞察,帮助企业改进产品质量、优化用户体验以及加强安全防护。Elasticsearch 作为一个分布式搜索和分析引擎,因其出色的性能和灵活性,成为了日志分析领域的首选工具之一。本文将探讨如何使用 Elasticsearch 作为日志分析平台的核心组件,并详细介绍 ELK(Elasticsearch, Logstash, Kibana)栈的搭建和配置流程。
129 4
|
3月前
|
存储 人工智能 自然语言处理
阿里云Elasticsearch AI场景语义搜索最佳实践
本文介绍了如何使用阿里云Elasticsearch结合搜索开发工作台搭建AI语义搜索。
17269 68
|
26天前
|
存储 缓存 自然语言处理
深度解析ElasticSearch:构建高效搜索与分析的基石
【9月更文挑战第8天】在数据爆炸的时代,如何快速、准确地从海量数据中检索出有价值的信息成为了企业面临的重要挑战。ElasticSearch,作为一款基于Lucene的开源分布式搜索和分析引擎,凭借其强大的实时搜索、分析和扩展能力,成为了众多企业的首选。本文将深入解析ElasticSearch的核心原理、架构设计及优化实践,帮助读者全面理解这一强大的工具。
114 7
|
2月前
|
人工智能 自然语言处理 搜索推荐
阿里云Elasticsearch AI搜索实践
本文介绍了阿里云 Elasticsearch 在AI 搜索方面的技术实践与探索。
18886 21
因为一个问题、我新学了一门技术 ElasticSearch 分布式搜索
这篇文章讲述了作者因为一个检索问题而学习了ElasticSearch技术,并分享了排查和解决ElasticSearch检索结果与页面展示不符的过程。
因为一个问题、我新学了一门技术 ElasticSearch 分布式搜索
|
1月前
|
JSON 监控 Java
Elasticsearch 入门:搭建高性能搜索集群
【9月更文第2天】Elasticsearch 是一个分布式的、RESTful 风格的搜索和分析引擎,基于 Apache Lucene 构建。它能够处理大量的数据,提供快速的搜索响应。本教程将指导你如何从零开始搭建一个基本的 Elasticsearch 集群,并演示如何进行简单的索引和查询操作。
100 3
|
3月前
|
数据采集 人工智能 安全
阿里云Elasticsearch 企业级AI搜索方案发布
本文从AI搜索落地的挑战、阿里云在RAG场景的实践、效果提升三个方面,深度解读阿里云Elasticsearch 企业级AI搜索方案。
342 8