Elasticsearch文本分析器

1. 前言

Elasticsearch数据搜索和关系型数据库的SQL查询最显著的区别就是:除了精准匹配和模糊查询,Elasticsearch还具备全文检索的能力,而全文检索的核心是文本分析。

文本分析会将长文本内容进行字符过滤和细粒度的分词,先将长文本里面一些无关紧要的字符给过滤掉,再按照语义将长文本切分为一个个单独的词,然后可能还会根据切分后的词再添加一些同义词,最终构建倒排索引用于全文检索 。

文本分析使得Elasticsearch能够执行全文检索召回相关的文档,而不仅仅是是精准匹配。如下示例,当用户搜索”苹果“二字,召回下面三个文档在ES看来都是合理的:

{"_id":"1","text":"什么品种的苹果更好吃呢?"
}
{"_id":"2","text":"Apple Store上海静安店今日开业!"
}
{"_id":"3","text":"番茄是水果还是蔬菜?"
}

1号文档召回是因为直接有“苹果”二字、2号文档召回可以理解为“Apple“和”苹果“是同义词、3号文档召回有点意外,如果分词的粒度很细就会导致”果“字被切分为一个单独的词,从而和搜索词匹配成功。

全文检索时,如果Elasticsearch没有召回预期的文档,就应该检查一下文本分析器的配置是否合理。

2. 分析器的构成

Elasticsearch规定,文本分析器由三个基本组件构成,分别是:

  • 0个或多个字符过滤器 character filters
  • 一个分词器 tokenizer
  • 0个或多个分词过滤器 token filters

2.1 字符过滤器

字符过滤器接收作为字符流的原始文本,并可以通过添加、删除或更改字符来转换该流。简单来说,就是字符过滤器可以在原始文本的基础上,做一些字符过滤、删除、替换等操作,在分词前做一些预处理的工作。

例如,字符过滤器可以把”&“符号替换成”and“、也可以去除HTML中的标签,保留文本内容。

Elasticsearch内置了三种字符过滤器,下面分别介绍。

html_strip 用于过滤HTML元素标签,如下示例,结果自动过滤掉了

标签

POST _analyze
{"char_filter": [{"type": "html_strip"}],"text": "<p><b>听我说</b>谢谢你,因为有你</p>"
}{"tokens": [{"token": """
听我说谢谢你,因为有你
""","start_offset": 0,"end_offset": 25,"type": "word","position": 0}]
}

mapping 用于替换字符,给定一个mappings数组,Elasticsearch扫描原始文本时每当遇到相同的Key就会替换成指定的Value。如下示例:

POST _analyze
{"char_filter": [{"type": "mapping","mappings": ["& => 和",":) => 开心",":( => 悲伤"]}],"text": "我&你独自:),独自:("
}{"tokens": [{"token": "我和你独自开心,独自悲伤","start_offset": 0,"end_offset": 12,"type": "word","position": 0}]
}

pattern_replace 使用正则表达式来匹配和替换字符,比如可以给重要信息如身份证号脱敏:

POST _analyze
{"char_filter": [{"type": "pattern_replace","pattern":"(\\d{6})\\d{8}(\\d{4})","replacement":"$1******$2"}],"text": "The ID number is:362330199001012345"
}{"tokens": [{"token": "The ID number is:362330******2345","start_offset": 0,"end_offset": 35,"type": "word","position": 0}]
}

2.2 分词器

分词器接收一个被字符过滤器预处理后的字符流作为输入,它是文本分析最重要的一个环节,直接决定了一段长文本会按照怎样的算法来切分成一个个分词。

除了切分文本,分词器还会保留以下信息:

  • 每个分词的相对位置,用于短语搜索和单词临近搜索
  • 字符偏移量,记录分词在原始文本中的出现的位置
  • 分词类型,记录分词的种类,是单词还是数字等

Elasticsearch 内置了大量的面向单词的分词器

以 standard 为例,它也是默认的分词器。它会按照Unicode文本分割算法定义的词边界将文本划分为术语,并且删除了大多数标点符号。对于英文,它会按照空格来分词;对于中文,它会按照一个个汉字来分词。

如下示例,对于英文分词效果还行,针对中文效果就不好了,切分成一个个汉字丢失了词意。

POST _analyze
{"tokenizer":"standard","text": "I am from China.我爱中国"
}分词结果
["I","am","from","China","我","爱","中","国"]

Elasticsearch 还内置了一些比较特殊的分词器:N-Gram Tokenizer,也叫 N元语法分词器。它会将单词分解成更小的片段,用于部分单词匹配,缺点是分词数量太多,占用更多的存储空间。

POST _analyze
{"tokenizer":{"type":"ngram","min_gram":2, // 分词最小长度"max_gram":3, // 分词最大长度"token_chars":["letter"] // 只切分字母},"text": "Elasticsearch 666"
}分词结果
["se","sea","ea","ear","ar","arc","rc","rch","ch"]

此外,Elasticsearch还内置了一些用于结构化文本的分词器,比如:keyword 是一个什么也不做的分词器,它的分词结果就是原始文本。

char_group 分词器会根据给定的字符集对原始文本做切分,它比正则表达式的效率要高,适用于分词规则简单的场景。

POST _analyze
{"tokenizer":{"type":"char_group","tokenize_on_chars":["_"]},"text": "I_am_from_China"
}分词结果
["I","am","from","China"]

再比如,path_hierarchy 会按照路径分隔符做分词,并输出每个子路径的分词结果。如下示例:

POST _analyze
{"tokenizer":{"type":"path_hierarchy"},"text": "/users/admin/a.txt"
}分词结果
["/users","/users/admin","/users/admin/a.txt"]

2.3 分词过滤器

分词过滤器接收来自分词器切分后的文本作为输入,并做最后处理。包括:改写词(转换大小写)、删除停用词、添加同义词等操作。

截止Elasticsearch8.13版本,官方内置了几十种分词过滤器,这里只介绍几个,其它参考官方文档。

apostrophe 分词过滤器会删除撇号后面的所有字符,包括撇号本身,适用于土耳其语。如下示例:

POST _analyze
{"tokenizer":"standard","filter":["apostrophe"],"text": "I'm 18 years old now"
}分词结果
["I","18","years","old","now"]

reverse 分词过滤器会反转切分后的每个词,这对于后缀检索非常有用。如下示例:

POST _analyze
{"tokenizer":"standard","filter":["reverse"],"text": "hello world"
}分词结果
["olleh","dlrow"]

stemmer 分词过滤器会根据分词的单词去掉复数、时态等,统一转换成对应的原型,这在英文搜索时非常有用。如下示例:

POST _analyze
{"tokenizer":"standard","filter":["stemmer"],"text": "they flying peoples"
}分词结果
["thei","fly","peopl"]

stop 分词过滤器器会删除分词中无意义的停用词,比如冠词、介词等,还可以自定义停用词黑名单。

如下示例,过滤后只保留了“apple”

POST _analyze
{"tokenizer":"standard","filter":["stop"],"text": "this is an apple"
}分词结果
["apple"]

3. 自定义分析器

Elasticsearch规定,任何分析器都由0个或多个字符过滤器、1个分词器、0个或多个分词过滤器组成,官方内置了大量的基础组件,同时又基于这些基础组件定义了一堆内置的分析器。如果这些内置分析器不能够满足我们的需求,我们也可以任意搭配组合定制化一个分析器。

假设,我们现在创建一个questions索引,用来索引问题,然后可以根据关键词搜索问题。question字段使用text类型,同时使用我们自定义的文本分析器my_analyzer。

假设自定义的文本分析器需要满足下列需求:

  • 自动过滤掉文本中的标点符号
  • 简单点,针对“/"符号来做分词吧
  • 自动过滤掉一些无意义的停用词,例如:“的”、“啊”
  • 使用同义词也能搜索到文档,例如搜索”Android“可以召回含“安卓”的文档

基于以上需求,我们可以先从字符过滤器、分词器、分词过滤器的顺序来慢慢调试我们的分析器。这里可以用到Elasticsearch提供的「_analyze」端点,它可以很方便的用来测试分析器的效果。

过滤标点符号可以用”mapping“实现,分词就用”char_group“,删除停用词用”stop“,最后同义词可以用”synonym“实现,最终自定义分析器的配置如下:

POST _analyze
{"char_filter": [{"type": "mapping","mappings": [", => ","。 => ","? => "]}],"tokenizer": {"type": "char_group","tokenize_on_chars": ["/"]},"filter":[{"type":"stop","stopwords":["的","呢","和"]},{"type":"synonym","synonyms":["安卓 => 安卓,Android","鸿蒙 => 鸿蒙,HarmonyOS,OpenHarmony"]}],"text": "鸿蒙/系统/和/安卓/系统/有/什么/区别/呢/?"
}

测试一下,分词结果如下所示,符合我们的需求:

["鸿蒙","HarmonyOS","OpenHarmony","系统","安卓","Android","系统","有","什么","区别"]

接下来就是创建索引时,指定我们自定义的分析器即可:

PUT questions
{"settings": {"analysis": {"analyzer": {"my_analyzer": {"char_filter": ["my_char_filter"],"tokenizer": "my_char_group","filter": ["stop_filter","synonym_filter"]}},"char_filter": {"my_char_filter": {"type": "mapping","mappings": [", => ","。 => ","? => "]}},"tokenizer": {"my_char_group": {"type": "char_group","tokenize_on_chars": ["/"]}},"filter": {"stop_filter": {"type": "stop","stopwords": ["的","呢","和"]},"synonym_filter": {"type": "synonym","synonyms": ["安卓 => 安卓,Android","鸿蒙 => 鸿蒙,HarmonyOS,OpenHarmony"]}}}},"mappings": {"properties": {"question": {"type": "text","analyzer": "my_analyzer","search_analyzer": "my_analyzer"}}}
}

索引一篇文档

POST questions/_doc
{"question":"鸿蒙/系统/和/安卓/系统/有/什么/区别/呢/?"
}

搜索”Android“,发现成功召回了预期的文档

GET questions/_search
{"query": {"match": {"question": "Android"}}
}{"took": 1,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 1,"relation": "eq"},"max_score": 0.32792777,"hits": [{"_index": "questions","_id": "y-SQx44BPIYet_3fDf9T","_score": 0.32792777,"_source": {"question": "鸿蒙/系统/和/安卓/系统/有/什么/区别/呢/?"}}]}
}

4. IK中文分析器

无论是Elasticsearch官方提供的分析器,还是我们自定义的分析器,都很难对中文内容有很好的分词效果,把一段中文切分成孤立的汉字会丢失语义。所以,我们需要一款针对中文的文本分析器,这里推荐 IK Analysis。

IK分析器需要单独安装,进入到Github页面:https://github.com/infinilabs/analysis-ik/releases,找到对应版本下载安装包放到Elasticsearch安装目录下的plugins目录,重启Elasticsearch即可使用。

IK Analysis 提供了两种中文分析器供我们使用,分别是:ik_max_word和ik_smart。

ik_max_word 切分的粒度更细,ik_smart 切分的粒度会粗一下,占用的存储空间也会相对少一些。一般推荐索引时使用ik_smart节省存储空间,搜索时使用 ik_max_word 切分出更多的词以便能搜索到结果。

如下示例,是ik_max_word的分词效果,分出10个词

POST _analyze
{"analyzer":"ik_max_word","text": "ik_max_word分词器的测试效果"
}分词结果
["ik_max_word","ik","max","word","分词器","分词","器","的","测试","效果"]

下面是ik_smart的分词效果,只切分出5个词

POST _analyze
{"analyzer":"ik_smart","text": "ik_smart分词器的测试效果"
}分词结果
["ik_smart","分词器","的","测试","效果"]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/448221.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IP地址查询在线小工具

IP属地查询工具 https://www.ipshudi.com/

嵌入式开发学习日记——认识指针及和数组函数的联系(c语言)

一、指针的定义 一般格式&#xff1a; 数据类型 * 指针变量名 [初始地址值]; 数据类型是指针所指向的地址处的数据类型&#xff0c;如 int、char、float 等。 符号 * 用于通知系统&#xff0c;这里定义的是一个指针变量&#xff0c;通常跟在类型关键字的后面&#xff0c;表示…

【C++笔记】string类深度解剖及其模拟实现

【C笔记】string类深度解剖及其模拟实现 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;C笔记 文章目录 【C笔记】string类深度解剖及其模拟实现前言一.string类说明1.1为什么实现string类1.2string类了解 二.string类的常用接口说明2.1str…

Nature Communications 英国伦敦大学等提出仿生自适应多平面触觉系统,实现机械与振动双重感知结合

触觉&#xff0c;作为人类感知外界并与之互动的重要方式&#xff0c;赋予了人类以辨识物体多重特性&#xff08;诸如纹理、硬度、可塑性及重量&#xff09;与捕捉微妙线索&#xff08;例如感知心跳或精准定位动脉振动&#xff09;的能力。这一感官机制不仅深化了人类对周围世界…

爬虫post请求

爬虫post请求 这一篇文章, 我们开始学习爬虫当中的post请求。 在讲post请求之前, 我们先来回顾一下get请求。 get请求: get请求的参数有三个, get(url, headers, params), 其中, params是可写可不写的。headers是请求头, 这个请求头在开发者工具里面的网络, 找到相应的请求, …

merlion的dashboard打开方法

安装好merlion包后&#xff0c;在anaconda prompt中进行如下图操作&#xff1a; 先进入创建好的虚拟环境&#xff1a;conda activate merlion再执行命令&#xff1a;python -m merlion.dashboard在浏览器中手动打开图中的地址&#xff1a; http://127.0.0.1:8050 打开后的界面…

Qt- QSS风格选择器常用属性选择器样式表盒子

1. 风格设置 Qt 提供了 3 种整体风格&#xff0c;使用 QStyleFactory::keys() 来获取 &#xff08;windowsvista 、Windows 、Fusion&#xff09; 可以在 main.cpp 中调用 setStyle 方法对应用程序进行全局风格的设置 int main(int argc, char *argv[]) {QApplication a(arg…

ElasticSearch+Kibana 8.1.0安装部署

Windows环境 通过百度网盘分享的文件&#xff1a;ElasticSearchKibanaik 链接&#xff1a;https://pan.baidu.com/s/14Bf9AkRjf5igaa10e18OWA?pwd1rmh 提取码&#xff1a;1rmh 下载后解压 命令都在bin目录下用cmd执行 一、ElasticSearch 注意&#xff1a;8.1.0自带jdk17&…

2024版51单片机教程

一、教程简介 前置基础

Linux云计算 |【第五阶段】ARCHITECTURE-DAY1

主要内容&#xff1a; 了解ELK分布式日志分析系统、Elasticsearch分布式集群搭建、Kibana搭建、使用kibana展示数据&#xff1b; 一、日志分析系统ELK概述 ELK 是 Elasticsearch、Logstash 和 Kibana 的缩写&#xff0c;是三款软件都是开源软件&#xff0c;通常是配合使用&am…

CentOS7安装Mysql5.7(ARM64架构)

1.第一步&#xff1a;下载 arm 版本离线 mysql 5.7 安装包 arm 版本离线 mysql 5.7 安装包 2.第二步&#xff1a;查询并卸载 CentOS 自带的数据库 Mariadb 找到数据库 mariadb&#xff0c;如果有会给出一个结果&#xff0c;结果是 mariadb 名称 rpm -qa | grep mariadb 如果…

64页精品PPT | 汽车经销商数据应用解决方案

汽车经销商正面临前所未有的盈利能力挑战。从18年起 &#xff0c;传统燃油车汽车行业开始步入低速增长阶段 &#xff0c;卖车已经挣不到钱 &#xff0c;利润往往来自任务完成的厂家返利&#xff1b;新兴的直营模式的出现 &#xff0c;冲击了传统授权经销的方式 &#xff0c;疫情…

matlab生成任意长度余弦波coe文件以及vivado仿真

一、matlab生成任意长度余弦波coe文件 clear clc close all width32; %rom的位宽 depth3600; %rom的深度 xlinspace(0,2*pi,depth); %在一个周期内产生3600个采样点 y_coscos(x); %生成余弦数据 y_cosround(y_cos*(2^(width-1)-1))2^(width-1)-1; %将余弦数据全部转换为…

用Eclipse运行第一个Java程序

1.左键双击在桌面“软件 (文件夹)”&#xff0c;打开该文件夹 2.左键双击“eclipse (文件夹)”&#xff0c;打开该文件夹 3.左键双击“eclipse (文件夹)”&#xff0c;打开该文件夹 4.左键双击“eclipse.exe”&#xff0c;运行这个可执行程序 5.左键单击“Ok&#xff08;按下按…

MySQL学习笔记(持续更新,目前到十一章锁)

1、Mysql概述 1.1 数据库相关概念 三个概念&#xff1a;数据库、数据库管理系统、SQL 名称全称简称数据库存储数据的仓库&#xff0c;数据是有组织的进行存储DataBase&#xff08;DB&#xff09;数据库管理系统操纵和管理数据库的大型软件DataBase Mangement System&#xf…

使用npm i报错node-sass失败问题解决

node 版本&#xff1a;v14.15.4 解决方法&#xff1a; npm config set sass_binary_sitehttps://npmmirror.com/mirrors/node-sass设置完之后&#xff0c;再npm i 就可以下载成功 亲测有效

视频汇聚平台EasyCVR支持云端录像丨监控存储丨录像回看丨录像计划丨录像配置

EasyCVR视频汇聚融合平台&#xff0c;是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。平台以其强大的视频处理、汇聚与融合能力&#xff0c;在构建视频监控系统中展现出了独特的优势。 EasyCVR视频汇聚平台可接入传统监控行业中高清网络摄像机的RTSP…

C++ | Leetcode C++题解之第475题供暖器

题目&#xff1a; 题解&#xff1a; class Solution { public:int findRadius(vector<int>& houses, vector<int>& heaters) {sort(houses.begin(), houses.end());sort(heaters.begin(), heaters.end());int ans 0;for (int i 0, j 0; i < houses.…

【Vue】Vue3.0 (十二)、watch对ref定义的基本类型、对象类型;reactive定义的对象类型的监视使用

上篇文章&#xff1a;【Vue】Vue3.0&#xff08;十一&#xff09;Vue 3.0 中 computed 计算属性概念、使用及示例 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Vue专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年10月16日12点45分 文章…

施磊C++ | 进阶学习笔记 | 5.设计模式

五、设计模式 文章目录 五、设计模式1.设计模式三大类型概述一、创建型设计模式二、结构型设计模式三、行为型设计模式 2.设计模式三大原则3.单例模式1.饿汉单例模式2.懒汉单例模式 4.线程安全的懒汉单例模式1.锁双重判断2.简洁的线程安全懒汉单例模式 5.简单工厂(Simple Facto…