倒排索引的初衷

倒排索引,它也是索引。索引,初衷都是为了快速检索到你要的数据。

我相信你一定知道mysql的索引,如果对某一个字段加了索引,一般来说查询该字段速度是可以有显著的提升。

每种数据库都有自己要解决的问题(或者说擅长的领域),对应的就有自己的数据结构,而不同的使用场景和数据结构,需要用不同的索引,才能起到最大化加快查询的目的。

对 Mysql 来说,是 B+ 树,对 Elasticsearch/Lucene 来说,是倒排索引。

倒排索引是什么

刚刚胖滚猪说到图书的例子,目录和索引页,其实就很形象的可以比喻为正排索引和倒排索引。为了进一步加深理解,再看看熟悉的搜索引擎。没有搜索引擎时,我们只能直接输入一个网址,然后获取网站内容,这时我们的行为是document -> words。此谓「正向索引」。后来,我们希望能够输入一个单词,找到含有这个单词,或者和这个单词有关系的文章,即word -> documents。于是我们把这种索引,叫「反向索引」,或者「倒排索引」。

好了,我们来总结一下:

倒排索引的实现

假如一篇文章当中,有这么一段话"胖滚猪编程让你收获快乐",我要通过"胖滚猪"这个词来搜索到这篇文章,那么应该如何实现呢。

我们是很容易想到,可以将这篇文章的词都拆开,拆分为"胖滚猪"、"编程"、"收获"、"快乐"。注意我们把没用的词,比如"让"去掉了。这个拆分短语的过程涉及到ES的分词,另外中文分词还是比较复杂的,不像英文分词一般用空格分隔就可以。等会我们再来说分词吧,现在你只要知道,我们是会按一定规则把文章单词拆分的。

那么拆开了,怎么去找呢?自然会维护一个单词和文档的对应关系,如图:



倒排索引的核心组成

1、单词词典:记录所有文档的单词,一般都比较大。还会记录单词到倒排列表的关联信息。

2、倒排列表:记录了单词对应的文档集合,由倒排索引项组成。倒排索引项包含如下信息:

  • 文档ID,用于获取原始信息
  • 单词频率TF,记录该单词在该文档中的出现次数,用于后续相关性算分
  • 位置Position,记录单词在文档中分词的位置,用于语句搜索(phrase query)
  • 偏移Offset,记录单词在文档的开始和结束位置,实现高亮显示

ES的倒排索引

下图是 Elasticsearch 中数据索引过程的流程。ES由 Analyzer 组件对文档执行一些操作并将具体子句拆分为 token/term,简单说就是分词,然后将这些术语作为倒排索引存储在磁盘中。

ES的JSON文档中的每一个字段,都有自己的倒排索引,当然你可以指定某些字段不做索引,优点是这样可以节省磁盘空间。但是不做索引的话字段无法被搜索到。

注意两个关键词:分词和倒排索引。倒排索引我相信你已经懂了!分词我们马上就来聊聊!

ES的分词

还是回到我们开头的那个查询例子,毕竟胖滚猪心心念念为什么会搜出两个文档!首先我们用_analyze来分析一下ES会如何对它进行分词及倒排索引:

现在你是不是一目了然了呢!先不管_analyze是何方神圣,反正你看到结果了,ES将它分成了一个个字,这是ES中默认的中文分词。掌握分词要先懂两个名词:analysis与analyzer

** analysis:**

文本分析,是将全文本转换为一系列单词的过程,也叫分词。analysis是通过analyzer(分词器)来实现的,可以使用Elasticearch内置的分词器,也可以自己去定制一些分词器。

** analyzer(分词器): **

由三部分组成:

  • Character Filter:将文本中html标签剔除掉。
  • Tokenizer:按照规则进行分词,在英文中按照空格分词
  • Token Filter:将切分的单词进行加工,小写,删除 stopwords(停顿词,a、an、the、is等),增加同义词

注意:除了在数据写入时将词条进行转换,查询的时候也需要使用相同的分析器对语句进行分析。即我们写入苹果的时候分词成了苹和果,查询苹果的时候同样也是分词成苹和果去查。

ES内置分词器

  • Standard Analyzer - 默认分词器,按词切分,小写处理
  • Simple Analyzer - 按照非字母切分(符号被过滤), 小写处理
  • Stop Analyzer - 小写处理,停用词过滤(the,a,is)
  • Whitespace Analyzer - 按照空格切分,不转小写
  • Keyword Analyzer - 不分词,直接将输入当作输出
  • Patter Analyzer - 正则表达式,默认\W+(非字符分割)
  • Language - 提供了30多种常见语言的分词器
  • Customer Analyzer 自定义分词器

看概念太虚了!一定要动手实操才有用!我们可以用_analyze进行分析,会输出分词后的结果,举两个例子吧!其他的你也要自己课后动手试试哦!

#默认分词器 按词切分 小写处理
GET _analyze
{
"analyzer": "standard",
"text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

#可以发现停用词被去掉了
GET _analyze
{
"analyzer": "stop",
"text": "2 running Quick brown-foxes leap over lazy dogs in the summer evening."
}

中文扩展分词器

现在来解决胖滚猪的问题,苹果明明一个词,不想让它分为两个呀!中文分词在所有搜索引擎中都是一个很大的难点,中文的句子应该是切分成一个个的词,但是一句中文,在不同的上下文,其实是不同的理解,例如: 这个苹果,不大好吃/这个苹果,不大,好吃。

有一些比较不错的中文分词插件:IK、THULAC等。我们可以试试用IK进行中文分词。

#安装插件
https://github.com/medcl/elasticsearch-analysis-ik/releases
在plugins目录下创建analysis-ik目录 解压zip包到当前目录 重启ES
#查看插件
bin/elasticsearch-plugin list
#查看安装的插件
GET http://localhost:9200/_cat/plugins?v

** IK分词器:支持自定义词库、支持热更新分词字典 **

  • ik_max_word: 会将文本做最细粒度的拆分,比如会将“这个苹果不大好吃”拆分为"这个,苹果,不大好,不大,好吃"等,会穷尽各种可能的组合;
  • ik_smart: 会做最粗粒度的拆分,比如会将“这个苹果不大好吃”拆分为"这个,苹果,不大,好吃"
curl -X GET "localhost:9200/_analyze?pretty" -H 'Content-Type: application/json' -d'
{
"analyzer" : "ik_max_word",
"text" : "这个苹果不大好吃"
}
'

** 如何使用分词器 **

列举了很多的分词器,那么在实际中该如何使用呢?看看下面这个代码演示就懂啦!

# 创建索引时候指定某个字段的分词器
PUT iktest
{
"mappings": {
"properties": {
"content": {
"type": "text",
"analyzer": "ik_smart"
}
}
}
}
# 插入一条文档
PUT iktest/_doc/1
{
"content":"这个苹果不大好吃"
}
# 测试分词效果
GET /iktest/_analyze
{
"field": "content",
"text": "这个苹果不大好吃"
}

注:本文来源于公众号[胖滚猪学编程],其中卡通形象来源于微信表情包"胖滚家族",且已获作者的许可。

本文来源于公众号【胖滚猪学编程】一个集颜值与才华于一身的女程序媛。以漫画形式让编程so easy and interesting。

【漫画】ES原理 必知必会的倒排索引和分词的更多相关文章

  1. Elasticsearch必知必会的干货知识一:ES索引文档的CRUD

    ​ 若在传统DBMS 关系型数据库中查询海量数据,特别是模糊查询,一般我们都是使用like %查询的值%,但这样会导致无法应用索引,从而形成全表扫描效率低下,即使是在有索引的字段精确值查找,面对海量数 ...

  2. Elasticsearch必知必会的干货知识二:ES索引操作技巧

    该系列上一篇文章<Elasticsearch必知必会的干货知识一:ES索引文档的CRUD> 讲了如何进行index的增删改查,本篇则侧重讲解说明如何对index进行创建.更改.迁移.查询配 ...

  3. Java并发必知必会第三弹:用积木讲解ABA原理

    Java并发必知必会第三弹:用积木讲解ABA原理 可落地的 Spring Cloud项目:PassJava 本篇主要内容如下 一.背景 上一节我们讲了程序员深夜惨遭老婆鄙视,原因竟是CAS原理太简单? ...

  4. 2015 前端[JS]工程师必知必会

    2015 前端[JS]工程师必知必会 本文摘自:http://zhuanlan.zhihu.com/FrontendMagazine/20002850 ,因为好东东西暂时没看懂,所以暂时保留下来,供以 ...

  5. [ 学习路线 ] 2015 前端(JS)工程师必知必会 (2)

    http://segmentfault.com/a/1190000002678515?utm_source=Weibo&utm_medium=shareLink&utm_campaig ...

  6. python网络爬虫,知识储备,简单爬虫的必知必会,【核心】

    知识储备,简单爬虫的必知必会,[核心] 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌 ...

  7. crypto必知必会

    crypto必知必会 最近参加了个ctf比赛,在i春秋,南邮方面刷了一些crypto密码学题目,从中也增长了不少知识,在此关于常见的密码学知识做个小总结! Base编码 Base编码中用的比较多的是b ...

  8. 关于TCP/IP,必知必会的十个经典问题[转]

    关于TCP/IP,必知必会的十个问题 原创 2018-01-25 Ruheng 技术特工队   本文整理了一些TCP/IP协议簇中需要必知必会的十大问题,既是面试高频问题,又是程序员必备基础素养. 一 ...

  9. Android程序员必知必会的网络通信传输层协议——UDP和TCP

    1.点评 互联网发展至今已经高度发达,而对于互联网应用(尤其即时通讯技术这一块)的开发者来说,网络编程是基础中的基础,只有更好地理解相关基础知识,对于应用层的开发才能做到游刃有余. 对于Android ...

  10. 迈向高阶:优秀Android程序员必知必会的网络基础

    1.前言 网络通信一直是Android项目里比较重要的一个模块,Android开源项目上出现过很多优秀的网络框架,从一开始只是一些对HttpClient和HttpUrlConnection简易封装使用 ...

随机推荐

  1. hdu3033 I love sneakers! 分组背包变形(详解)

    这个题很怪,一开始没仔细读题,写了个简单的分组背包交上去,果不其然WA. 题目分析: 分组背包问题是这样描述的:有K组物品,每组 i 个,费用分别为Ci ,价值为Vi,每组物品是互斥的,只能取一个或者 ...

  2. 再也不用c刷题了!!——c++刷题必备

    致读者: 博主是一名数据科学与大数据专业大二的学生,真正的一个互联网萌新,写博客一方面是为了记录自己的学习历程,一方面是希望能够帮助到很多和自己一样处于困惑的读者.由于水平有限,博客中难免会有一些错误 ...

  3. mac OS Apache Tomcat 启动/停止服务

    进入Tomcat下的bin目录 启动Tomcat命令 ./startup.sh Tomcat 默认端口 8080 停止Tomcat服务命令 ./shutdown.sh 执行tomcat ./shutd ...

  4. 图论--2-SAT--POJ 3905 Perfect Election

    Perfect Election Time Limit: 5000MS         Memory Limit: 65536K Total Submissions: 964         Acce ...

  5. python selenium(用例断言)

    1.if ...else ...判断进行断言 from time import * from selenium import webdriver "): driver = webdriver ...

  6. web安全笔记

    判断网站是否伪静态 把.html后缀即可或者加.php?id=99 例子:33_99.html   去掉.html和_变成33.php?id=99 即可判断是否伪静态 判断网站是否在win或者linu ...

  7. 大富翁 线段树+二分 +dfs

    https://csustacm.fun/problem/2033 这个题目还是比较简单的,但是比赛的时候没有像清楚,用了一个不太熟悉的数据结构主席树, 所以出现了bug,主席树的bug是真的难找. ...

  8. IDEA 2020.1 安装教程

    目录 IDEA 2020.1 安装教程 准备工作 破解教程 IDEA 2020.1 安装教程 IDEA 2020.1 安装教程 Win 10 版 64位操作系统 准备工作 IDEA旗舰版下载地址 je ...

  9. 网上流行护眼色的RGB值和颜色代码

    网上流行护眼色的RGB值和颜色代码   绿豆沙色能有效的减轻长时间用电脑的用眼疲劳!色调:85,饱和度:123,亮度:205: RGB颜色红:199,绿:237,蓝:204:十六进制颜色:#C7EDC ...

  10. 【Spark】不熟悉Spark-shell常用参数?这一张图就够了