百亿级数据全文检索工具,ElasticSearch鼻祖Lucene

什么是全文检索?

什么叫做全文检索呢?这要从我们生活中的数据说起。我们生活中的数据总体分为两种:
结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。
非结构化数据(也叫全文数据) :指不定长或无固定格式的数据,如邮件,word文档等。
半结构化数据:如XML,HTML等,当根据需要可按结构化数据来处理,也可抽取出纯文本按非结构化数据来处理。

按照数据的分类,搜索也分为两种:
对结构化数据的搜索 :如对数据库的搜索,用SQL语句。再如对元数据的搜索,如利用windows搜索对文件名,类型,修改时间进行搜索等。
对非结构化数据的搜索 :如利用windows的搜索也可以搜索文件内容,Linux下的grep命令,再如用Google和百度可以搜索大量内容数据。

对非结构化数据也即对全文数据的搜索主要有两种方法:
顺序扫描法 (Serial Scanning)
所谓顺序扫描,比如要找内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。如利用windows的搜索也可以搜索文件内容,只是相当的慢。如果你有一个80G硬盘,如果想在上面找到一个内容包含某字符串的文件,不花他几个小时,怕是做不到。Linux下的grep命令也是这一种方式。
这种方法比较原始,但对于小数据量的文件,这种方法还是最直接,最方便的。但是对于大量的文件,这种方法就很慢了。
全文检索
将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜一个索,从而达到搜索相对较快的目的。

Apache Lucene是什么?

Apache Lucene其实就是apache提供的一个开源关于搜索引擎的类库,囊括了较为全面的有关搜索引擎相关的技术解决思路,使得现如今的soler以及ElasticSearch尤为的火爆,不管是在互联网项目中以及大数据领域占据了不可多得的地位。

索引

正排索引

正排索引.png

为什么顺序扫描的速度慢:其实是由于我们想要搜索的信息和非结构化数据中所存储的信息不一致造成的。

倒排索引

非结构化数据中所存储的信息是每个文件包含哪些字符串,也即已知文件,欲求字符串相对容易,也即是从文件到字符串的映射。而我们想搜索的信息是哪些文件包含此字符串,也即已知字符串,欲求文件,也即从字符串到文件的映射。两者恰恰相反。于是如果索引总能够保存从字符串到文件的映射,则会大大提高搜索速度。


倒排索引.png

倒排索引一般表示为一个关键词,然后是它的频度(出现的次数),位置(出现在哪一篇文章或网页中,及有关的日期,作者等信息),它相当于为互联网上几千亿页网页做了一个索引,好比一本书的目录、标签一般。想看哪一个主题相关的章节,直接根据目录即可找到相关的页面。不必再从书的第一页到最后一页,一页一页的查找。

例如:
文章 head content
文章1 超级塞亚人 我是超级塞亚人我喜欢吃苹果,我不是天朝的人,也不是地球人
文章2 天朝大国 我大天朝威武,我大天朝13亿人,我大天朝
文章3 游泳 游泳有很多好方法
文章4 动画片 喜欢看动画片,尤其是七龙珠,因为里面有塞亚人,而且塞亚人喜欢吃苹果,他们不是地球人
文章5 运动 喜欢运动,喜欢跑步,喜欢游泳,喜欢健身,喜欢
文章6 打炮 我喜欢打游戏,我最幸福的时光就是在天朝吃着苹果玩打炮游戏

关键字:塞亚人 苹果 天朝 地球 七龙珠 游泳 喜欢

关键词 索引
塞亚人 文章1[1],文章4[2], n n n
苹果 文章1[1],文章4[1],文章6[1], n n n
天朝 文章1[1],文章2[2],文章6[1], n n n n
地球 文章1[1],文章4[1], n n
游泳 文章3[1],文章5[1], n n
七龙珠 文章4[1], n
喜欢 文章1[1],文章4[2],文章5[4],文章6[1], n n n n n n n n

倒排索引2个重要构成:
1.倒排文件(inverted file):存储倒排索引的物理文件
2.倒排索引组成:单词词典和倒排文件。

何为倒排索引

核心术语

倒排索引.png

Index
Lucene的索引(Index)是由多个文件组成,这些文件被存放在同一目录下。
Token
词元(Token)在Lucene与在自然语言处理(NLP)中的概念相同,表示“词元”。词元即自然语言中的基本单位:在中文表现为一个独立的字或词,在英文中表现为一个单词。
Term
经过分词和语言处理后得到的字符串,它是索引的最小单位。
Field
不同的域可以指定不同的索引方式,比如指定不同的分词方式,是否构建索引,是否存储等。
Document
文档是索引的基本单位,代表一些域(Field)的集合。在Lucene中,Document是一种逻辑文件。可以近似地认为它表示的是计算机中的一个文件。这个Document是一种抽象的表示,它从各种维度来描述一个数据源中的每一条数据。
可以使用关系型数据库中的记录来理解Document,数据库的每一条记录可以表示为一个Document,而每一列可以用Field来表示。但不同的是,Document并非结构化的,并没有schema的约束。不同的文档保存在不同的段中的,一个段中可以包含多篇文档。新添加的文档被单独保存在一个新生成的段中,随着段的合并,不同的文档会合并到至相同的段中。
Segment
一个Lucene的索引(Index)由多个段组成,段与段之间是独立的。当添加索引时会生成新的Document,但并不是把新的Document 立即添加到同一个索引文件,而是把它们先被写入到不同的小文件(Segment),当小文件的个数达到阈值(段的个数,段中包含的文件数等)时,然后再合并成一个大索引文件(不同的段可以合并)。
Directory
Lucene索引的存放位置。
文档模型

文档名称 扩展名 说明
Segments File segments_N 保存提交点的信息
Lock File write.lock 写文件锁,用于防止多个IndexWriters同时写一个文件
Segment Info .si 保存段的元数据信息
Compound File .cfs, .cfe 采用混合格式下该文件包括其他所有格式的文件
Fields .fnm 保存域信息
Field Index .fdx 保存指向域数据的指针
Field Data .fdt 保存域数据
Term Dictionary .tim 保存词项信息
Term Index .tip Term Dictionary的索引信息
Frequencies .doc 记录文档信息,以及文档中词项对应的词频
Positions .pos 记录词项的位置信息
Payloads .pay 全文索引的字段,使用了一些像payloads的高级特性会有该文件,保存了term在doc中的一些高级特性
Norms .nvd, .nvm 文件保存索引字段加权数据
Per-Document Values .dvd, .dvm lucene的docvalues文件,即数据的列式存储,用作聚合和排序
Term Vector Index .tvx 记录文档数据记录中的偏移量
Term Vector Documents .tvd 记录有词项向量的文档的信息
Term Vector Fields .tvf 词项向量的域级别信息
Live Documents .liv 存活文件的信息
Point values .dii, .dim 记录被索引的点

Segment_N
Segments_N为段的元数据信息文件。保存了此索引包含多少个段,每个段包含多少篇文档等信息。

Segment_N.png

Lucene当前活跃的Segment都会存在一个Segment Info文件里,也就是segments_N。如果有多个segments_N, 那么序号最大的就是最新的。
1.Format:索引文件格式的版本号。由于Lucene是在不断开发过程中的,不同版本的Lucene可能有不同索引文件格式,所以规定了文件格式的版本号。
2.Version:索引的版本号
3.NameCount:下一个新段的段名
4.SegCount:段的个数
[Lucece图形化工具Luke:]{https://www.github.com/DmitryKey/luke}
域文件格式
域元数据文件(fnm)
一个段(Segment)包含多个域,每个域都有一些元数据信息,保存在.fnm文件中,.fnm文件的格式如下:
域文件格式.png

域的数据信息存储在 .fdt 和 .fdx 文件中。其中,.fdx 文件中存放FieldValuesPositon,指向.fdt文件,也就是说域的具体数据是存放在fdt文件中的。
域数据文件(fdt)
真正保存域(stored field)信息的是fdt文件。
假如在一个Segment中包含N篇文档,那么fdt文档中一会有N个项,每一个项都保存对应文档的域信息。
FieldCount,表示此文档包含的域数目
紧接着是FieldCount域信息项,每个项保存一个域的信息。对于每一个域的信息:
FieldNum是域编号
接着是一个8bit的byte。根据填充值(0或1),代表不同的意义。最低一位表示此域是否分词;倒数第二位表示此域保存的是字符串数据还是二进制数据;倒数第三位表示此域是否被压缩。最后存储的是这个存储域的值。
域索引文件(fdx)
由域数据文件格式可知,每篇文档包含的域的个数、每个存储域的值都是不一样的。
因为segment中会包含N篇文档(Document),每篇文档占用的大小也是不一样的,那么如何快速在fdt文件中辨别每一篇文档的起始地址和终止地址?如何能够更快的找到第N篇文档的存储域的信息呢?
这就需要借助域索引文件。域索引文件也总共有N个项(如果segment中包含N篇Document),每篇文档都对应一个项,每一项中都存储一个Long型数值(大小固定),该数值代表文档在fdt中的起始地址偏移量。
域索引文件格式.png

词向量文件
词向量信息是从索引(Index)到文档(Document)到域(Field)到词(Term)的正向信息,有了词向量信息,就可以得到一篇文档包含哪些词的信息 。
词向量文件格式.png

词向量数据文件(tvd)
首先,是此文档包含域的个数:NumFields
之后,是一个NumFields大小的数组,数组每一项都是域号
最后,是(NumField - 1)大小的数组。每一篇文档的第一个域的偏移量信息存储在 tvx 文件中。而其他(NumFields - 1)域的偏移量就是第一个域的偏移量加上第(NumField - 1)个数组的值。
词向量索引文件(tvx)
一个段(segment)包含N篇文档,此文件就有N项,每一项代表一篇文档。每一项包含两部分信息:
第一部分是词向量文档文件(tvd)中此文档的偏移量
第二部分是词向量文件(tvf)中此文档的第一个域的偏移量
词向量域文件(tvf)
该文件包含了此段(Segment)中的所有域,并且不对文档做区分,到底第几个域到第几个域是属于那篇文件,是由tvx文件中的第一个域的偏移量以及tvd文件中的(NumField - 1)个域的偏移量来决定哪些域数据属于哪个文档。
对于每一个域,包含如下项:
首先,是说明此域中包含的多少(NumTerms)个词(Term)
之后,是8bit的byte(最后一位指定是否保存位置信息,倒数第二位表示是否保存偏移量信息)
最后,NumTerms个项的数组,每一项代表一个词(Term)。每一个词,由如下几部分构成
词的文本TermText
词频TermFreq(词在该文档中出现的次数)
词的位置
词的偏移量

创建倒排索引流程


全文检索的索引创建过程一般有以下几步:
第一步(原始素材)
为了方便说明索引创建过程,这里特意用两个文件为例:
文件一:Students should be allowed to go out with their friends, but not allowed to drink beer.
文件二:My friend Jerry went to school to see his students but found them drunk which is not allowed.
第二步(分词)
将原文档传给分词器(Tokenizer),分词器会做以下几件事情( 此过程称为Tokenize) :
将文档分成一个一个单独的单词。
去除标点符号。
去除停词(Stop word) 。
所谓停词(Stop word)就是一种语言中最普通的一些单词,由于没有特别的意义,因而大多数情况下不能成为搜索的关键词,因而创建索引时,这种词会被去掉而减少索引的大小。
每一种语言的分词组件(Tokenizer),都有一个停词(stop word)集合。
经过分词(Tokenizer) 后得到的结果称为词元(Token) ,如下:
第三步(语言处理)
将得到的词元(Token)传给语言处理组件(Linguistic Processor),语言处理组件(linguistic processor)主要是对得到的词元(Token)做一些同语言相关的处理。
对于英语,语言处理组件(Linguistic Processor) 一般做以下几点:
变为小写(Lowercase) 。
将单词缩减为词根形式,如“cars ”到“car ”等。这种操作称为:stemming 。
将单词转变为词根形式,如“drove ”到“drive ”等。这种操作称为:lemmatization 。
经过语言处理,得到的词(Term)如下:
第四步(构建索引)
至此,Lucene有关于搜索引擎以及基础知识点还有如何创建索引和大家分享完,欢迎大家和我一起分享学习!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容

  • 1. Lucene 官网 1). 概述 Lucene是一款高性能的、可扩展的信息检索(IR)工具库。信息检索是指文...
    _凌浩雨阅读 926评论 0 1
  • 目录结构:1.全文检索 2.Lucene入门3.Lucene进阶 全文检索 一, 生活中的搜索:1.Win...
    CoderZS阅读 1,669评论 0 12
  • 1. 案例分析:什么时全文检索,如何实现全文检索   1.1 案例   实现一个文件的搜索功能,通过关键字搜索文件...
    东方舵手阅读 1,180评论 0 1
  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,284评论 0 9
  • 12点,一辆辆景区观光车已整装待发,我们是最先几批上的,绕过几条街道,就往效外前进!沿路不断见到被推到一半的废弃民...
    西泠静阅读 318评论 0 0