前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >elasticsearch倒排索引与分词

elasticsearch倒排索引与分词

作者头像
小旋锋
发布于 2019-01-21 11:02:20
发布于 2019-01-21 11:02:20
1.5K00
代码可运行
举报
运行总次数:0
代码可运行

倒排索引

  • 正排索引:文档id到单词的关联关系
  • 倒排索引:单词到文档id的关联关系

示例: 对以下三个文档去除停用词后构造倒排索引

image

倒排索引-查询过程

查询包含“搜索引擎”的文档

  1. 通过倒排索引获得“搜索引擎”对应的文档id列表,有1,3
  2. 通过正排索引查询1和3的完整内容
  3. 返回最终结果
倒排索引-组成
  • 单词词典(Term Dictionary)
  • 倒排列表(Posting List)
单词词典(Term Dictionary)

单词词典的实现一般用B+树,B+树构造的可视化过程网址: B+ Tree Visualization

关于B树和B+树

  1. 维基百科-B树
  2. 维基百科-B+树
  3. B树和B+树的插入、删除图文详解

image

倒排列表(Posting List)
  • 倒排列表记录了单词对应的文档集合,有倒排索引项(Posting)组成
  • 倒排索引项主要包含如下信息:
    1. 文档id用于获取原始信息
    2. 单词频率(TF,Term Frequency),记录该单词在该文档中出现的次数,用于后续相关性算分
    3. 位置(Posting),记录单词在文档中的分词位置(多个),用于做词语搜索(Phrase Query)
    4. 偏移(Offset),记录单词在文档的开始和结束位置,用于高亮显示

image

B+树内部结点存索引,叶子结点存数据,这里的 单词词典就是B+树索引,倒排列表就是数据,整合在一起后如下所示

note: B+树索引中文和英文怎么比较大小呢?unicode比较还是拼音呢?

image

ES存储的是一个JSON格式的文档,其中包含多个字段,每个字段会有自己的倒排索引

分词

分词是将文本转换成一系列单词(Term or Token)的过程,也可以叫文本分析,在ES里面称为Analysis

image

分词器

分词器是ES中专门处理分词的组件,英文为Analyzer,它的组成如下:

  • Character Filters:针对原始文本进行处理,比如去除html标签
  • Tokenizer:将原始文本按照一定规则切分为单词
  • Token Filters:针对Tokenizer处理的单词进行再加工,比如转小写、删除或增新等处理

分词器调用顺序

image

Analyze API

ES提供了一个可以测试分词的API接口,方便验证分词效果,endpoint是_analyze

  • 可以直接指定analyzer进行测试

image

  • 可以直接指定索引中的字段进行测试
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
POST test_index/doc
{
  "username": "whirly",
  "age":22
}

POST test_index/_analyze
{
  "field": "username",
  "text": ["hello world"]
}
  • 可以自定义分词器进行测试
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
POST _analyze
{
  "tokenizer": "standard",
  "filter": ["lowercase"],
  "text": ["Hello World"]
}

预定义的分词器

ES自带的分词器有如下:

  • Standard Analyzer
    • 默认分词器
    • 按词切分,支持多语言
    • 小写处理
  • Simple Analyzer
    • 按照非字母切分
    • 小写处理
  • Whitespace Analyzer
    • 空白字符作为分隔符
  • Stop Analyzer
    • 相比Simple Analyzer多了去除请用词处理
    • 停用词指语气助词等修饰性词语,如the, an, 的, 这等
  • Keyword Analyzer
    • 不分词,直接将输入作为一个单词输出
  • Pattern Analyzer
    • 通过正则表达式自定义分隔符
    • 默认是\W+,即非字词的符号作为分隔符
  • Language Analyzer
    • 提供了30+种常见语言的分词器

示例:停用词分词器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
POST _analyze
{
  "analyzer": "stop",
  "text": ["The 2 QUICK Brown Foxes jumped over the lazy dog's bone."]
}

结果

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "tokens": [
    {
      "token": "quick",
      "start_offset": 6,
      "end_offset": 11,
      "type": "word",
      "position": 1
    },
    {
      "token": "brown",
      "start_offset": 12,
      "end_offset": 17,
      "type": "word",
      "position": 2
    },
    {
      "token": "foxes",
      "start_offset": 18,
      "end_offset": 23,
      "type": "word",
      "position": 3
    },
    {
      "token": "jumped",
      "start_offset": 24,
      "end_offset": 30,
      "type": "word",
      "position": 4
    },
    {
      "token": "over",
      "start_offset": 31,
      "end_offset": 35,
      "type": "word",
      "position": 5
    },
    {
      "token": "lazy",
      "start_offset": 40,
      "end_offset": 44,
      "type": "word",
      "position": 7
    },
    {
      "token": "dog",
      "start_offset": 45,
      "end_offset": 48,
      "type": "word",
      "position": 8
    },
    {
      "token": "s",
      "start_offset": 49,
      "end_offset": 50,
      "type": "word",
      "position": 9
    },
    {
      "token": "bone",
      "start_offset": 51,
      "end_offset": 55,
      "type": "word",
      "position": 10
    }
  ]
}

中文分词

  • 难点
    • 中文分词指的是将一个汉字序列切分为一个一个的单独的词。在英文中,单词之间以空格作为自然分界词,汉语中词没有一个形式上的分界符
    • 上下文不同,分词结果迥异,比如交叉歧义问题
  • 常见分词系统
    • IK:实现中英文单词的切分,可自定义词库,支持热更新分词词典
    • jieba:支持分词和词性标注,支持繁体分词,自定义词典,并行分词等
    • Hanlp:由一系列模型与算法组成的Java工具包,目标是普及自然语言处理在生产环境中的应用
    • THUAC:中文分词和词性标注
安装ik中文分词插件
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 在Elasticsearch安装目录下执行命令,然后重启es
bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.3.0/elasticsearch-analysis-ik-6.3.0.zip

# 如果由于网络慢,安装失败,可以先下载好zip压缩包,将下面命令改为实际的路径,执行,然后重启es
bin/elasticsearch-plugin install file:///path/to/elasticsearch-analysis-ik-6.3.0.zip
  • ik测试 - ik_smart
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
POST _analyze
{
  "analyzer": "ik_smart",
  "text": ["公安部:各地校车将享最高路权"]
}

# 结果
{
  "tokens": [
    {
      "token": "公安部",
      "start_offset": 0,
      "end_offset": 3,
      "type": "CN_WORD",
      "position": 0
    },
    {
      "token": "各地",
      "start_offset": 4,
      "end_offset": 6,
      "type": "CN_WORD",
      "position": 1
    },
    {
      "token": "校车",
      "start_offset": 6,
      "end_offset": 8,
      "type": "CN_WORD",
      "position": 2
    },
    {
      "token": "将",
      "start_offset": 8,
      "end_offset": 9,
      "type": "CN_CHAR",
      "position": 3
    },
    {
      "token": "享",
      "start_offset": 9,
      "end_offset": 10,
      "type": "CN_CHAR",
      "position": 4
    },
    {
      "token": "最高",
      "start_offset": 10,
      "end_offset": 12,
      "type": "CN_WORD",
      "position": 5
    },
    {
      "token": "路",
      "start_offset": 12,
      "end_offset": 13,
      "type": "CN_CHAR",
      "position": 6
    },
    {
      "token": "权",
      "start_offset": 13,
      "end_offset": 14,
      "type": "CN_CHAR",
      "position": 7
    }
  ]
}
  • ik测试 - ik_max_word
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
POST _analyze
{
  "analyzer": "ik_max_word",
  "text": ["公安部:各地校车将享最高路权"]
}

# 结果
{
  "tokens": [
    {
      "token": "公安部",
      "start_offset": 0,
      "end_offset": 3,
      "type": "CN_WORD",
      "position": 0
    },
    {
      "token": "公安",
      "start_offset": 0,
      "end_offset": 2,
      "type": "CN_WORD",
      "position": 1
    },
    {
      "token": "部",
      "start_offset": 2,
      "end_offset": 3,
      "type": "CN_CHAR",
      "position": 2
    },
    {
      "token": "各地",
      "start_offset": 4,
      "end_offset": 6,
      "type": "CN_WORD",
      "position": 3
    },
    {
      "token": "校车",
      "start_offset": 6,
      "end_offset": 8,
      "type": "CN_WORD",
      "position": 4
    },
    {
      "token": "将",
      "start_offset": 8,
      "end_offset": 9,
      "type": "CN_CHAR",
      "position": 5
    },
    {
      "token": "享",
      "start_offset": 9,
      "end_offset": 10,
      "type": "CN_CHAR",
      "position": 6
    },
    {
      "token": "最高",
      "start_offset": 10,
      "end_offset": 12,
      "type": "CN_WORD",
      "position": 7
    },
    {
      "token": "路",
      "start_offset": 12,
      "end_offset": 13,
      "type": "CN_CHAR",
      "position": 8
    },
    {
      "token": "权",
      "start_offset": 13,
      "end_offset": 14,
      "type": "CN_CHAR",
      "position": 9
    }
  ]
}
  • ik两种分词模式ik_max_word 和 ik_smart 什么区别?
    • ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合;
    • ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”。

自定义分词

当自带的分词无法满足需求时,可以自定义分词,通过定义Character Filters、Tokenizer和Token Filters实现

Character Filters
  • 在Tokenizer之前对原始文本进行处理,比如增加、删除或替换字符等
  • 自带的如下:
    • HTML Strip Character Filter:去除HTML标签和转换HTML实体
    • Mapping Character Filter:进行字符替换操作
    • Pattern Replace Character Filter:进行正则匹配替换
  • 会影响后续tokenizer解析的position和offset信息
Character Filters测试
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
POST _analyze
{
  "tokenizer": "keyword",
  "char_filter": ["html_strip"],
  "text": ["<p>I&apos;m so <b>happy</b>!</p>"]
}

# 结果
{
  "tokens": [
    {
      "token": """

I'm so happy!

""",
      "start_offset": 0,
      "end_offset": 32,
      "type": "word",
      "position": 0
    }
  ]
}
Tokenizers
  • 将原始文本按照一定规则切分为单词(term or token)
  • 自带的如下:
    • standard 按照单词进行分割
    • letter 按照非字符类进行分割
    • whitespace 按照空格进行分割
    • UAX URL Email 按照standard进行分割,但不会分割邮箱和URL
    • Ngram 和 Edge NGram 连词分割
    • Path Hierarchy 按照文件路径进行分割
Tokenizers 测试
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
POST _analyze
{
  "tokenizer": "path_hierarchy",
  "text": ["/path/to/file"]
}

# 结果
{
  "tokens": [
    {
      "token": "/path",
      "start_offset": 0,
      "end_offset": 5,
      "type": "word",
      "position": 0
    },
    {
      "token": "/path/to",
      "start_offset": 0,
      "end_offset": 8,
      "type": "word",
      "position": 0
    },
    {
      "token": "/path/to/file",
      "start_offset": 0,
      "end_offset": 13,
      "type": "word",
      "position": 0
    }
  ]
}
Token Filters
  • 对于tokenizer输出的单词(term)进行增加、删除、修改等操作
  • 自带的如下:
    • lowercase 将所有term转为小写
    • stop 删除停用词
    • Ngram 和 Edge NGram 连词分割
    • Synonym 添加近义词的term
Token Filters测试
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
POST _analyze
{
  "text": [
    "a Hello World!"
  ],
  "tokenizer": "standard",
  "filter": [
    "stop",
    "lowercase",
    {
      "type": "ngram",
      "min_gram": 4,
      "max_gram": 4
    }
  ]
}

# 结果
{
  "tokens": [
    {
      "token": "hell",
      "start_offset": 2,
      "end_offset": 7,
      "type": "<ALPHANUM>",
      "position": 1
    },
    {
      "token": "ello",
      "start_offset": 2,
      "end_offset": 7,
      "type": "<ALPHANUM>",
      "position": 1
    },
    {
      "token": "worl",
      "start_offset": 8,
      "end_offset": 13,
      "type": "<ALPHANUM>",
      "position": 2
    },
    {
      "token": "orld",
      "start_offset": 8,
      "end_offset": 13,
      "type": "<ALPHANUM>",
      "position": 2
    }
  ]
}
自定义分词

自定义分词需要在索引配置中设定 char_filter、tokenizer、filter、analyzer等

自定义分词示例:

  • 分词器名称:my_custom</li>
  • 过滤器将token转为大写
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
PUT test_index_1
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_custom_analyzer": {
          "type":      "custom",
          "tokenizer": "standard",
          "char_filter": [
            "html_strip"
          ],
          "filter": [
            "uppercase",
            "asciifolding"
          ]
        }
      }
    }
  }
}
自定义分词器测试
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
POST test_index_1/_analyze
{
  "analyzer": "my_custom_analyzer",
  "text": ["<p>I&apos;m so <b>happy</b>!</p>"]
}

# 结果
{
  "tokens": [
    {
      "token": "I'M",
      "start_offset": 3,
      "end_offset": 11,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "SO",
      "start_offset": 12,
      "end_offset": 14,
      "type": "<ALPHANUM>",
      "position": 1
    },
    {
      "token": "HAPPY",
      "start_offset": 18,
      "end_offset": 27,
      "type": "<ALPHANUM>",
      "position": 2
    }
  ]
}
分词使用说明

分词会在如下两个时机使用:

  • 创建或更新文档时(Index Time),会对相应的文档进行分词处理
  • 查询时(Search Time),会对查询语句进行分词
    • 查询时通过analyzer指定分词器
    • 通过index mapping设置search_analyzer实现
    • 一般不需要特别指定查询时分词器,直接使用索引分词器即可,否则会出现无法匹配的情况
分词使用建议
  • 明确字段是否需要分词,不需要分词的字段就将type设置为keyword,可以节省空间和提高写性能
  • 善用_analyze API,查看文档的分词结果

更多内容请访问我的个人网站: http://laijianfeng.org 参考文档:

  1. elasticsearch 官方文档
  2. 慕课网 Elastic Stack从入门到实践
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-08-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小旋锋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
如何在Debian 9上为用户目录设置vsftpd
FTP是文件传输协议的缩写,是一种曾经广泛用于在客户端和服务器之间移动文件的网络协议。它已被更快,更安全,更方便的文件传输方式所取代。很多休闲互联网用户希望直接从他们的Web浏览器下载https,命令行用户更容易使用的安全协议,如scp或SFTP。
丰一川
2018/11/05
2.9K0
FTP服务器
FTP服务器(File Transfer Protocol Server)是在互联网上提供文件存储和访问服务的计算机,它们依照FTP协议提供服务。
胡齐
2019/09/23
13K0
FTP服务器
如何在Ubuntu 16.04上为用户目录设置vsftpd
FTP是文件传输协议的缩写,是一种曾经广泛用于在客户端和服务器之间移动文件的网络协议。它已被更快,更安全,更方便的文件传输方式所取代。许多休闲网民希望直接用https从他们的Web浏览器下载它,而且命令行用户更容易去使用安全的协议,如scp或SFTP。
GeekZ
2018/10/25
2.3K0
Linux云服务器下搭建FTP服务器
FTP工作模式简介 FTP工作会启动两个通道:控制通道和数据通道。 控制通道一般由客户端发起,数据连接分两种:port(主动)和pasv(被动)。 PORT模式: 在客户端需要接收数据时,ftp_cl
吴奇
2017/03/06
17.8K0
如何在Ubuntu 18.04上为用户目录设置vsftpd
FTP是文件传输协议的缩写,是一种曾经广泛用于在客户端和服务器之间移动文件的网络协议。它已被更快,更安全,更方便的文件传输方式所取代。许多普通网民希望通过https直接从他们的网络浏览器下载,命令行用户更有可能使用安全协议,如scp或SFTP。
葡萄
2018/08/08
2.8K0
配置VSFTP文件服务器
FTP 文件传输协议.用于互联网上的控制文件的双向传输,使用FTP来传输时,其实是具有一定程度的危险性,因为数据在因特网上面是完全没有受到保护的明文传输方式,VSFTP是一个基于GPL发布的类Unix系统上使用的FTP服务器软件,从名称定义上基本可以看出,这是为了解决ftp传输安全性问题的.
微软技术分享
2022/12/28
6.1K0
配置VSFTP文件服务器
如何在Ubuntu 18.04上使用VSFTP快速设置FTP服务器
如果你想将应用程序迁移到最新版本Ubuntu Linux服务器中,并且需要快速启动并运行FTP服务器。如何操作?这实际上非常简单。这里将使用VSFTP服务器向您展示如何做到这一点。
星哥玩云
2022/07/14
1.9K0
CentOS 6.5基于AD域账号联动认证的vsftpd结合SSL加密服务器配置
二、实施步骤: 1、系统基础设置 计算机名、IP地址、网关、子网掩码、DNS设置 2、安装所需要的软件 Yum install httpd -y Yum install vsftpd* -y Yum install pam* -y Yum install mod_ssl* -y
星哥玩云
2022/06/30
9580
ubuntu下部署FTP服务器
FTP是TCP/IP协议组中的协议之一,即文件传输协议,工作在TCP模型的第四层(应用层),使用TCP传输使用交互式的访问,允许客户端指定文件类型和格式,一般为ASCII码和文本格式。
dogfei
2020/07/31
2.4K1
Ubuntu 16.04 配置vsftpd使用 ssl 传输
1、创建证书 $ sudo openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem 2、配置 vsftpd $ sudo vim /etc/vsftpd.conf 替换证书: rsa_cert_file=/etc/ssl/private/vsftpd.pem rsa_private_key_file=/etc/ssl/pri
前Thoughtworks-杨焱
2021/12/08
4730
关于FTP搭建问题
1. 匿名服务器的连接(独立的服务器) 在/etc/vsftpd.conf(或在/etc/vsftpd/vsftpd.conf)配置文件中添加如下几项: Anonymous_enable=yes (允许匿名登陆) Dirmessage_enable=yes (切换目录时,显示目录下.message的内容) Local_umask=022 (FTP上本地的文件权限,默认是077) Connect_form_port_20=yes (启用FTP数据端口的数据连接)* Xferlog_enable=yes (激活上传和下载的日志) Xferlog_std_format=yes (使用标准的日志格式) Ftpd_banner=XXXXX (欢迎信息) Pam_service_name=vsftpd (验证方式)* Listen=yes (独立的VSFTPD服务器)* 注释:以上配置只能连接FTP服务器,不能上传和下载 注:其中所有和日志欢迎信息相关连的都是可选项,打了星号的无论什么帐户都要添加,是属于FTP的基本选项
云知识Online
2018/05/03
2.5K0
网络系统管理Linux环境——StorageSrv之VSFTPD
禁止使用不安全的 FTP,请使用“CSK Global Root CA”证书颁发机构,颁发的证书,启用 FTPS 服务;
冷影玺
2023/10/11
4220
网络系统管理Linux环境——StorageSrv之VSFTPD
ubuntu 16.04 搭建ftp服务器
如果登录后出现如下错误,则在/etc/vsftpd.conf文件内添加allow_writeable_chroot=YES
全栈程序员站长
2022/09/14
1.6K0
Linux下FTP虚拟账号环境部署总结
vsftp的用户有三种类型:匿名用户、系统用户、虚拟用户。 1)匿名登录:在登录FTP时使用默认的用户名,一般是ftp或anonymous。 2)本地用户登录:使用系统用户登录,在/etc/passwd中。 3)虚拟用户登录:这是FTP专有用户,有两种方式实现虚拟用户,本地数据文件和数据库服务器。 FTP虚拟用户是FTP服务器的专有用户,使用虚拟用户账号可以提供集中管理的FTP根目录,方便了管理员的管理,同时将用于FTP登录的用户名、密码与系统用户账号区别开,进一步增强了FTP服务器的安全性。某种意义上来说
洗尽了浮华
2018/01/22
4.8K0
Linux下FTP虚拟账号环境部署总结
CentOS7安装vsftpd
本地用户的主目录有时候并不能作为ftp的根目录,也可以对每个用户设置设置FTP根目录
十毛
2023/10/16
6290
Ubuntu Server 第九章 文件服务
在文件服务之前,先提下网络。网络是一个意外的产物,最早在美国国防部提出,出于战争的需要,担心军事指挥中心被摧毁,设计了一套去中心化的系统(APPAnet)。NSF利用APPanet发展出来的TCP/IP通讯协议,建立的NTFnet广域网,后来越来越多的组织接入使NSfnet成为Internet的骨干网之一。总结一下
天钧
2019/07/25
1.6K0
Ubuntu Server 第九章 文件服务
在Ubuntu系统上搭建Ftp服务器,并传输文件
新建 /etc/vsftpd.chroot_list 文件,在里面添加登录ftp服务器的linux用户
AnieaLanie
2021/12/27
10.5K0
CentOS7下搭建vsftpd服务器(本地用户模式)
anonymous_enable=NO #禁止匿名登录FTP服务器
yuanfan2012
2020/04/26
4.6K0
CentOS7下vsftpd over SSL/TLS加密传输配置实践
之前有介绍过CentOS下搭建vsftpd服务器,可以参考如下文章 CentOS7下搭建vsftpd服务器(本地用户模式) 下面开启SSL/TLS用于FTP安全加密传输 1、生成自签证书 cd /etc/pki/tls/certs/ openssl req -x509 -nodes -newkey rsa:2048 -keyout vsftpd.pem -out vsftpd.pem -days 365 [root@VM_Server ~]# cd /etc/pki/tls/certs/ [roo
yuanfan2012
2020/08/13
2.1K0
CentOS7下vsftpd over SSL/TLS加密传输配置实践
Linux搭建FTP服务器
注:ftpusers和user_list两个文件可理解为vsftp的黑名单,可在vsftpd.conf中开启userlist_deny参数即可生效,无论如何,我们创建的ftp用户不在这两个文件中即可保证可以正常使用。
用户6914340
2021/10/09
15.8K0
Linux搭建FTP服务器
推荐阅读
相关推荐
如何在Debian 9上为用户目录设置vsftpd
更多 >
LV.1
雪梦科技研发
目录
  • 倒排索引
    • 倒排索引-查询过程
    • 倒排索引-组成
    • 单词词典(Term Dictionary)
    • 倒排列表(Posting List)
  • 分词
    • 分词器
  • Analyze API
  • 预定义的分词器
  • 中文分词
    • 安装ik中文分词插件
  • 自定义分词
    • Character Filters
    • Character Filters测试
    • Tokenizers
    • Tokenizers 测试
    • Token Filters
    • Token Filters测试
    • 自定义分词
    • 自定义分词器测试
    • 分词使用说明
    • 分词使用建议
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文