精华内容
参与话题
问答
  • 全文检索的基本原理

    千次阅读 2018-06-15 14:55:20
    所以在了解Lucene之前要费一番工夫了解一下全文检索。那么什么叫做全文检索呢?这要从我们生活中的数据说起。我们生活中的数据总体分为两种:结构化数据 和非结构化数据 。结构化数据: 指具有固定格式或有限长度...

    一、总论

    根据http://lucene.apache.org/java/docs/index.html 定义:

    Lucene 是一个高效的,基于Java 的全文检索库。

    所以在了解Lucene之前要费一番工夫了解一下全文检索。

    那么什么叫做全文检索呢?这要从我们生活中的数据说起。

    我们生活中的数据总体分为两种:结构化数据 和非结构化数据 。

    • 结构化数据: 指具有固定格式或有限长度的数据,如数据库,元数据等。
    • 非结构化数据: 指不定长或无固定格式的数据,如邮件,word文档等。

    当然有的地方还会提到第三种,半结构化数据,如XML,HTML等,当根据需要可按结构化数据来处理,也可抽取出纯文本按非结构化数据来处理。

    非结构化数据又一种叫法叫全文数据。

    按照数据的分类,搜索也分为两种:

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

    对非结构化数据也即对全文数据的搜索主要有两种方法:

    一种是顺序扫描法 (Serial Scanning): 所谓顺序扫描,比如要找内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。如利用windows的搜索也可以搜索文件内容,只是相当的慢。如果你有一个80G硬盘,如果想在上面找到一个内容包含某字符串的文件,不花他几个小时,怕是做不到。Linux下的grep命令也是这一种方式。大家可能觉得这种方法比较原始,但对于小数据量的文件,这种方法还是最直接,最方便的。但是对于大量的文件,这种方法就很慢了。

    有人可能会说,对非结构化数据顺序扫描很慢,对结构化数据的搜索却相对较快(由于结构化数据有一定的结构可以采取一定的搜索算法加快速度),那么把我们的非结构化数据想办法弄得有一定结构不就行了吗?

    这种想法很天然,却构成了全文检索的基本思路,也即将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。

    这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引 。

    这种说法比较抽象,举几个例子就很容易明白,比如字典,字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找一个字只能顺序扫描。然而字的某些信息可以提取出来进行结构化处理,比如读音,就比较结构化,分声母和韵母,分别只有几种可以一一列举,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据——也即对字的解释。

    这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search) 。

    下面这幅图来自《Lucene in action》,但却不仅仅描述了Lucene的检索过程,而是描述了全文检索的一般过程。

    [图]全文检索的一般过程

     

    全文检索大体分两个过程,索引创建 (Indexing) 和搜索索引 (Search) 。

    • 索引创建:将现实世界中所有的结构化和非结构化数据提取信息,创建索引的过程。
    • 搜索索引:就是得到用户的查询请求,搜索创建的索引,然后返回结果的过程。

    于是全文检索就存在三个重要问题:

    1. 索引里面究竟存些什么?(Index)

    2. 如何创建索引?(Indexing)

    3. 如何对索引进行搜索?(Search)

    下面我们顺序对每个个问题进行研究。

     

    二、索引里面究竟存些什么

    索引里面究竟需要存些什么呢?

    首先我们来看为什么顺序扫描的速度慢:

    其实是由于我们想要搜索的信息和非结构化数据中所存储的信息不一致造成的。

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

    由于从字符串到文件的映射是文件到字符串映射的反向过程,于是保存这种信息的索引称为反向索引 。

    反向索引的所保存的信息一般如下:

    假设我的文档集合里面有100篇文档,为了方便表示,我们为文档编号从1到100,得到下面的结构

    [图]字典及倒排表结构

    左边保存的是一系列字符串,称为词典 。

    每个字符串都指向包含此字符串的文档(Document)链表,此文档链表称为倒排表 (Posting List)。

    有了索引,便使保存的信息和要搜索的信息一致,可以大大加快搜索的速度。

    比如说,我们要寻找既包含字符串“lucene”又包含字符串“solr”的文档,我们只需要以下几步:

    1. 取出包含字符串“lucene”的文档链表。

    2. 取出包含字符串“solr”的文档链表。

    3. 通过合并链表,找出既包含“lucene”又包含“solr”的文件。

    [图]倒排表合并过程

    看到这个地方,有人可能会说,全文检索的确加快了搜索的速度,但是多了索引的过程,两者加起来不一定比顺序扫描快多少。的确,加上索引的过程,全文检索不一定比顺序扫描快,尤其是在数据量小的时候更是如此。而对一个很大量的数据创建索引也是一个很慢的过程。

    然而两者还是有区别的,顺序扫描是每次都要扫描,而创建索引的过程仅仅需要一次,以后便是一劳永逸的了,每次搜索,创建索引的过程不必经过,仅仅搜索创建好的索引就可以了。

    这也是全文搜索相对于顺序扫描的优势之一:一次索引,多次使用。

     

    三、如何创建索引

    全文检索的索引创建过程一般有以下几步:

    第一步:一些要索引的原文档(Document)。

    为了方便说明索引创建过程,这里特意用两个文件为例:

    文件一: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)。

    分词组件(Tokenizer)会做以下几件事情( 此过程称为Tokenize) :

    1. 将文档分成一个一个单独的单词。

    2. 去除标点符号。

    3. 去除停词(Stop word) 。

    所谓停词(Stop word)就是一种语言中最普通的一些单词,由于没有特别的意义,因而大多数情况下不能成为搜索的关键词,因而创建索引时,这种词会被去掉而减少索引的大小。

    英语中挺词(Stop word)如:“the”,“a”,“this”等。

    对于每一种语言的分词组件(Tokenizer),都有一个停词(stop word)集合。

    经过分词(Tokenizer) 后得到的结果称为词元(Token) 。

    在我们的例子中,便得到以下词元(Token):

    “Students”,“allowed”,“go”,“their”,“friends”,“allowed”,“drink”,“beer”,“My”,“friend”,“Jerry”,“went”,“school”,“see”,“his”,“students”,“found”,“them”,“drunk”,“allowed”。

     

    第三步:将得到的词元(Token)传给语言处理组件(Linguistic Processor)。

    语言处理组件(linguistic processor)主要是对得到的词元(Token)做一些同语言相关的处理。

    对于英语,语言处理组件(Linguistic Processor) 一般做以下几点:

    1. 变为小写(Lowercase) 。

    2. 将单词缩减为词根形式,如“cars ”到“car ”等。这种操作称为:stemming 。

    3. 将单词转变为词根形式,如“drove ”到“drive ”等。这种操作称为:lemmatization 。

     

    Stemming 和 lemmatization的异同:

    • 相同之处:Stemming和lemmatization都要使词汇成为词根形式。
    • 两者的方式不同:
      • Stemming采用的是“缩减”的方式:“cars”到“car”,“driving”到“drive”。
      • Lemmatization采用的是“转变”的方式:“drove”到“drove”,“driving”到“drive”。
    • 两者的算法不同:
      • Stemming主要是采取某种固定的算法来做这种缩减,如去除“s”,去除“ing”加“e”,将“ational”变为“ate”,将“tional”变为“tion”。
      • Lemmatization主要是采用保存某种字典的方式做这种转变。比如字典中有“driving”到“drive”,“drove”到“drive”,“am, is, are”到“be”的映射,做转变时,只要查字典就可以了。
    • Stemming和lemmatization不是互斥关系,是有交集的,有的词利用这两种方式都能达到相同的转换。

    语言处理组件(linguistic processor)的结果称为词(Term) 。

    在我们的例子中,经过语言处理,得到的词(Term)如下:

    “student”,“allow”,“go”,“their”,“friend”,“allow”,“drink”,“beer”,“my”,“friend”,“jerry”,“go”,“school”,“see”,“his”,“student”,“find”,“them”,“drink”,“allow”。

     

    也正是因为有语言处理的步骤,才能使搜索drove,而drive也能被搜索出来。

     

    第四步:将得到的词(Term)传给索引组件(Indexer)。

    索引 组件(Indexer)主要做以下几件事情:

    1. 利用得到的词(Term)创建一个字典。

    在我们的例子中字典如下:

    TermDocument ID
    student1
    allow1
    go1
    their1
    friend1
    allow1
    drink1
    beer1
    my2
    friend2
    jerry2
    go2
    school2
    see2
    his2
    student2
    find2
    them2
    drink2
    allow2

     

    2. 对字典按字母顺序进行排序。

     

    TermDocument ID
    allow1
    allow1
    allow2
    beer1
    drink1
    drink2
    find2
    friend1
    friend2
    go1
    go2
    his2
    jerry2
    my2
    school2
    see2
    student1
    student2
    their1
    them2

    3. 合并相同的词(Term) 成为文档倒排(Posting List) 链表。

    [图]倒排表结构

     

    在此表中,有几个定义:

    • Document Frequency 即文档频次,表示总共有多少文件包含此词(Term)。
    • Frequency 即词频率,表示此文件中包含了几个此词(Term)。

    所以对词(Term) “allow”来讲,总共有两篇文档包含此词(Term),从而词(Term)后面的文档链表总共有两项,第一项表示包含“allow”的第一篇文档,即1号文档,此文档中,“allow”出现了2次,第二项表示包含“allow”的第二个文档,是2号文档,此文档中,“allow”出现了1次。

    到此为止,索引已经创建好了,我们可以通过它很快的找到我们想要的文档。

    而且在此过程中,我们惊喜地发现,搜索“drive”,“driving”,“drove”,“driven”也能够被搜到。因为在我们的索引中,“driving”,“drove”,“driven”都会经过语言处理而变成“drive”,在搜索时,如果您输入“driving”,输入的查询语句同样经过我们这里的一到三步,从而变为查询“drive”,从而可以搜索到想要的文档。

     

     

    三、如何对索引进行搜索?

    到这里似乎我们可以宣布“我们找到想要的文档了”。

    然而事情并没有结束,找到了仅仅是全文检索的一个方面。不是吗?如果仅仅只有一个或十个文档包含我们查询的字符串,我们的确找到了。然而如果结果有一千个,甚至成千上万个呢?那个又是您最想要的文件呢?

    打开Google吧,比如说您想在微软找份工作,于是您输入“Microsoft job”,您却发现总共有22600000个结果返回。好大的数字呀,突然发现找不到是一个问题,找到的太多也是一个问题。在如此多的结果中,如何将最相关的放在最前面呢?

    [图]Google的搜索实例

    当然Google做的很不错,您一下就找到了jobs at Microsoft。想象一下,如果前几个全部是“Microsoft does a good job at software industry…”将是多么可怕的事情呀。

    如何像Google一样,在成千上万的搜索结果中,找到和查询语句最相关的呢?

    如何判断搜索出的文档和查询语句的相关性呢?

    这要回到我们第三个问题:如何对索引进行搜索?

    搜索主要分为以下几步:

    第一步:用户输入查询语句。

    查询语句同我们普通的语言一样,也是有一定语法的。

    不同的查询语句有不同的语法,如SQL语句就有一定的语法。

    查询语句的语法根据全文检索系统的实现而不同。最基本的有比如:AND, OR, NOT等。

    举个例子,用户输入语句:lucene AND learned NOT Hadoop

    说明用户想找一个包含lucene和learned然而不包括hadoop的文档。

    第二步:对查询语句进行词法分析,语法分析,及语言处理。

    由于查询语句有语法,因而也要进行语法分析,语法分析及语言处理。

    1. 词法分析主要用来识别单词和关键字。

    如上述例子中,经过词法分析,得到单词有lucene,learned,hadoop, 关键字有AND, NOT。

    如果在词法分析中发现不合法的关键字,则会出现错误。如lucene AMD learned,其中由于AND拼错,导致AMD作为一个普通的单词参与查询。

    2. 语法分析主要是根据查询语句的语法规则来形成一棵语法树。

    如果发现查询语句不满足语法规则,则会报错。如lucene NOT AND learned,则会出错。

    如上述例子,lucene AND learned NOT hadoop形成的语法树如下:

    [图]语法树

     

    3. 语言处理同索引过程中的语言处理几乎相同。

    如learned变成learn等。

    经过第二步,我们得到一棵经过语言处理的语法树。

    [图]经过语言处理的语法树

     

    第三步:搜索索引,得到符合语法树的文档。

    此步骤有分几小步:

    1. 首先,在反向索引表中,分别找出包含lucene,learn,hadoop的文档链表。
    2. 其次,对包含lucene,learn的链表进行合并操作,得到既包含lucene又包含learn的文档链表。
    3. 然后,将此链表与hadoop的文档链表进行差操作,去除包含hadoop的文档,从而得到既包含lucene又包含learn而且不包含hadoop的文档链表。
    4. 此文档链表就是我们要找的文档。

    第四步:根据得到的文档和查询语句的相关性,对结果进行排序。

    虽然在上一步,我们得到了想要的文档,然而对于查询结果应该按照与查询语句的相关性进行排序,越相关者越靠前。

    如何计算文档和查询语句的相关性呢?

    不如我们把查询语句看作一片短小的文档,对文档与文档之间的相关性(relevance)进行打分(scoring),分数高的相关性好,就应该排在前面。

    那么又怎么对文档之间的关系进行打分呢?

    这可不是一件容易的事情,首先我们看一看判断人之间的关系吧。

    首先 看一个人,往往有很多要素 ,如性格,信仰,爱好,衣着,高矮,胖瘦等等。

    其次 对于人与人之间的关系,不同的要素重要性不同 ,性格,信仰,爱好可能重要些,衣着,高矮,胖瘦可能就不那么重要了,所以具有相同或相似性格,信仰,爱好的人比较容易成为好的朋友,然而衣着,高矮,胖瘦不同的人,也可以成为好的朋友。

    因而判断人与人之间的关系,首先要找出哪些要素对人与人之间的关系最重要 ,比如性格,信仰,爱好。其次要判断两个人的这些要素之间的关系 ,比如一个人性格开朗,另一个人性格外向,一个人信仰佛教,另一个信仰上帝,一个人爱好打篮球,另一个爱好踢足球。我们发现,两个人在性格方面都很积极,信仰方面都很善良,爱好方面都爱运动,因而两个人关系应该会很好。

     

    我们再来看看公司之间的关系吧。

    首先 看一个公司,有很多人组成,如总经理,经理,首席技术官,普通员工,保安,门卫等。

    其次对于公司与公司之间的关系,不同的人重要性不同 ,总经理,经理,首席技术官可能更重要一些,普通员工,保安,门卫可能较不重要一点。所以如果两个公司总经理,经理,首席技术官之间关系比较好,两个公司容易有比较好的关系。然而一位普通员工就算与另一家公司的一位普通员工有血海深仇,怕也难影响两个公司之间的关系。

    因而判断公司与公司之间的关系,首先要找出哪些人对公司与公司之间的关系最重要 ,比如总经理,经理,首席技术官。其次要判断这些人之间的关系 ,不如两家公司的总经理曾经是同学,经理是老乡,首席技术官曾是创业伙伴。我们发现,两家公司无论总经理,经理,首席技术官,关系都很好,因而两家公司关系应该会很好。

     

    分析了两种关系,下面看一下如何判断文档之间的关系 了。

    首先,一个文档有很多词(Term)组成 ,如search, lucene, full-text, this, a, what等。

    其次对于文档之间的关系,不同的Term重要性不同 ,比如对于本篇文档,search, Lucene, full-text就相对重要一些,this, a , what可能相对不重要一些。所以如果两篇文档都包含search, Lucene,fulltext,这两篇文档的相关性好一些,然而就算一篇文档包含this, a, what,另一篇文档不包含this, a, what,也不能影响两篇文档的相关性。

    因而判断文档之间的关系,首先找出哪些词(Term)对文档之间的关系最重要,如search, Lucene, fulltext。然后判断这些词(Term)之间的关系。

     

    找出词(Term) 对文档的重要性的过程称为计算词的权重(Term weight) 的过程。

    计算词的权重(term weight)有两个参数,第一个是词(Term),第二个是文档(Document)。

    词的权重(Term weight)表示此词(Term)在此文档中的重要程度,越重要的词(Term)有越大的权重(Term weight),因而在计算文档之间的相关性中将发挥更大的作用。

    判断词(Term) 之间的关系从而得到文档相关性的过程应用一种叫做向量空间模型的算法(Vector Space Model) 。

    下面仔细分析一下这两个过程:

    1. 计算权重(Term weight)的过程。

    影响一个词(Term)在一篇文档中的重要性主要有两个因素:

    • Term Frequency (tf):即此Term在此文档中出现了多少次。tf 越大说明越重要。
    • Document Frequency (df):即有多少文档包含次Term。df 越大说明越不重要。

    容易理解吗?词(Term)在文档中出现的次数越多,说明此词(Term)对该文档越重要,如“搜索”这个词,在本文档中出现的次数很多,说明本文档主要就是讲这方面的事的。然而在一篇英语文档中,this出现的次数更多,就说明越重要吗?不是的,这是由第二个因素进行调整,第二个因素说明,有越多的文档包含此词(Term), 说明此词(Term)太普通,不足以区分这些文档,因而重要性越低。

    这也如我们程序员所学的技术,对于程序员本身来说,这项技术掌握越深越好(掌握越深说明花时间看的越多,tf越大),找工作时越有竞争力。然而对于所有程序员来说,这项技术懂得的人越少越好(懂得的人少df小),找工作越有竞争力。人的价值在于不可替代性就是这个道理。

    道理明白了,我们来看看公式:

    [图]权重计算公式

    [图]权重计算公式变量

     

    这仅仅只term weight计算公式的简单典型实现。实现全文检索系统的人会有自己的实现,Lucene就与此稍有不同。

    2. 判断Term之间的关系从而得到文档相关性的过程,也即向量空间模型的算法(VSM)。

    我们把文档看作一系列词(Term),每一个词(Term)都有一个权重(Term weight),不同的词(Term)根据自己在文档中的权重来影响文档相关性的打分计算。

    于是我们把所有此文档中词(term)的权重(term weight) 看作一个向量。

    Document = {term1, term2, …… ,term N}

    Document Vector = {weight1, weight2, …… ,weight N}

    同样我们把查询语句看作一个简单的文档,也用向量来表示。

    Query = {term1, term 2, …… , term N}

    Query Vector = {weight1, weight2, …… , weight N}

    我们把所有搜索出的文档向量及查询向量放到一个N维空间中,每个词(term)是一维。

    如图:

    [图]向量空间模型

     

    我们认为两个向量之间的夹角越小,相关性越大。

    所以我们计算夹角的余弦值作为相关性的打分,夹角越小,余弦值越大,打分越高,相关性越大。

    有人可能会问,查询语句一般是很短的,包含的词(Term)是很少的,因而查询向量的维数很小,而文档很长,包含词(Term)很多,文档向量维数很大。你的图中两者维数怎么都是N呢?

    在这里,既然要放到相同的向量空间,自然维数是相同的,不同时,取二者的并集,如果不含某个词(Term)时,则权重(Term Weight)为0。

     

    相关性打分公式如下:

    [图]相关性打分的公式

     

    举个例子,查询语句有11个Term,共有三篇文档搜索出来。其中各自的权重(Term weight),如下表格。

     

    t1

    t2

    t3

    t4

    t5

    t6

    t7

    t8

    t9

    t10

    t11

    D1

    0

    0

    .477

    0

    .477

    .176

    0

    0

    0

    .176

    0

    D2

    0

    .176

    0

    .477

    0

    0

    0

    0

    .954

    0

    .176

    D3

    0

    .176

    0

    0

    0

    .176

    0

    0

    0

    .176

    .176

    Q

    0

    0

    0

    0

    0

    .176

    0

    0

    .477

    0

    .176

    于是计算,三篇文档同查询语句的相关性打分分别为:

    [图]文档一的打分计算

    [图]文档二的打分计算

    [图]文档三的打分计算

     

    于是文档二相关性最高,先返回,其次是文档一,最后是文档三。

    到此为止,我们可以找到我们最想要的文档了。

    说了这么多,其实还没有进入到Lucene,而仅仅是信息检索技术(Information retrieval)中的基本理论,然而当我们看过Lucene后我们会发现,Lucene是对这种基本理论的一种基本的的实践。所以在以后分析Lucene的文章中,会常常看到以上理论在Lucene中的应用。

    在进入Lucene之前,对上述索引创建和搜索过程所一个总结,如图:

    此图参照http://www.lucene.com.cn/about.htm 中文章《开放源代码的全文检索引擎Lucene》

    [图]索引创建和搜索过程

     

    1. 索引过程:

    1) 有一系列被索引文件

    2) 被索引文件经过语法分析和语言处理形成一系列词(Term) 。

    3) 经过索引创建形成词典和反向索引表。

    4) 通过索引存储将索引写入硬盘。

    2. 搜索过程:

    a) 用户输入查询语句。

    b) 对查询语句经过语法分析和语言分析得到一系列词(Term) 。

    c) 通过语法分析得到一个查询树。

    d) 通过索引存储将索引读入到内存。

    e) 利用查询树搜索索引,从而得到每个词(Term) 的文档链表,对文档链表进行交,差,并得到结果文档。

    f) 将搜索到的结果文档对查询的相关性进行排序。

    g) 返回查询结果给用户。

    展开全文
  • 全文检索

    万次阅读 2018-08-14 08:40:24
    本文我将为大家讲解全文检索技术——Lucene,现在这个技术用到的比较多,我觉得大家还是应该掌握一下,不说多精通,但是应该有所了解。在讲解之前,我们先来看一个案例,通过该案例引出全文检索技术——Lucene。 ...

    本文我将为大家讲解全文检索技术——Lucene,现在这个技术用到的比较多,我觉得大家还是应该掌握一下,不说多精通,但是应该有所了解。在讲解之前,我们先来看一个案例,通过该案例引出全文检索技术——Lucene。

    案例

    实现一个文件的搜索功能,通过关键字搜索文件,凡是文件名或文件内容包括关键字的文件都需要找出来。还可以根据中文词语进行查询,并且需要支持多个条件查询。本案例中的原始内容就是磁盘上的文件,如下图: 
    这里写图片描述

    需求分析

    数据库搜索

    数据库中的搜索很容易实现,通常都是使用sql语句进行查询,而且能很快的得到查询结果。为什么数据库搜索很容易呢?因为数据库中的数据存储是有规律的,有行有列而且数据格式、数据长度都是固定的。

    数据分类

    我们生活中的数据总体分为两种:结构化数据和非结构化数据。

    • 结构化数据:指具有固定格式或有限长度的数据,如数据库中的数据,元数据等。
    • 非结构化数据:指不定长或无固定格式的数据,如邮件,word文档等磁盘上的文件。

    非结构化数据查询方法

    1. 顺序扫描法(Serial Scanning) 
      所谓顺序扫描,比如要找内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。如利用windows的搜索也可以搜索文件内容,只是相当的慢。
    2. 全文检索(Full-text Search) 
      将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。 
      例如:字典。字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找一个字只能顺序扫描。然而字的某些信息可以提取出来进行结构化处理,比如读音,就比较结构化,分声母和韵母,分别只有几种可以一一列举,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据——也即对字的解释。 
      这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。 
      虽然创建索引的过程也是非常耗时的,但是索引一旦创建就可以多次使用,全文检索主要处理的是查询,所以耗时间创建索引是值得的。

    如何实现全文检索

    可以使用Lucene实现全文检索。Lucene是apache下的一个开放源代码的全文检索引擎工具包(提供了Jar包,实现全文检索的类库)。它提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便地在目标系统中实现全文检索的功能。 
    注意:Lucene只是一个引擎,只是一个工具包,如果使用Lucene开发全文检索功能,要记住Lucene是不能单独运行的

    全文检索技术的应用场景

    对于数据量大、数据结构不固定的数据可采用全文检索方式搜索。例如:

    • 使用全文检索技术可以实现搜索引擎(百度、google…),搜索引擎可以搜索互联网上所有的内容(网页、pdf电子书、视频、音乐)。 
      Lucene和搜索引擎的区别:搜索引擎是对外提供全文检索服务,是可以单独运行的。Lucene只是一个工具包不能单独运行,需要在project中加入lucene的jar包,最终project在JVM中运行。
    • 使用全文检索技术可以实现站内搜索,站内搜索只能搜索本网站的信息(网页、pdf电子书、视频、音乐、关系数据库中的信息等等),比如:电商网站搜索商品信息,论坛网站搜索网内帖子。

    Lucene实现全文检索的流程

    索引和搜索流程图

    索引和搜索流程图如下: 
    这里写图片描述
    1. 绿色表示索引过程,对要搜索的原始内容进行索引构建一个索引库,索引过程包括:确定原始内容即要搜索的内容→采集文档→创建文档→分析文档→索引文档。 
    2. 红色表示搜索过程,从索引库中搜索内容,搜索过程包括:用户通过搜索界面→创建查询→执行搜索,从索引库搜索→渲染搜索结果。

    从上面了解到的知识点也可看出,索引和搜索流程图也可表示为: 
    这里写图片描述 
    总结:全文检索过程分为索引、搜索两个过程:

    • 索引 
      1. 从关系数据库中、互联网上、文件系统采集源数据(要搜索的目标信息),源数据的来源是很广泛的。
      2. 将源数据采集到一个统一的地方,要创建索引,将索引创建到一个索引库(文件系统)中,从源数据库中提取关键信息,从关键信息中抽取一个一个,词和源数据是有关联的。也即创建索引时,词和源数据有关联,索引库中记录了这个关联,如果找到了词就说明找到了源数据(http的网页、pdf电子书等……)。
    • 搜索 
      1. 用户执行搜索(全文检索)编写查询关键字。
      2. 从索引库中搜索索引,根据查询关键字搜索索引库中的一个一个词
      3. 展示搜索的结果。

    创建索引

    对文档索引的过程,将用户要搜索的文档内容进行索引,索引存储在索引库(index)中。 
    这里我们要搜索的文档是磁盘上的文本文件,根据案例描述:凡是文件名或文件内容包括关键字的文件都要找出来,这里要对文件名和文件内容创建索引。

    获得原始文档

    原始文档是指要索引和搜索的内容。原始内容包括互联网上的网页、数据库中的数据、磁盘上的文件等。本案例中的原始内容就是磁盘上的文件,如下图: 
    这里写图片描述
    从互联网上、数据库、文件系统中等数据源处获取需要搜索的原始信息,这个过程就是信息采集,信息采集的目的是为了对原始内容进行索引。针对不同的源数据,使用不同的技术进行采集获得原始文档:

    1. 针对互联网上的数据,使用http协议抓取html网页到本地,生成一个html文件。
    2. 针对关系数据库中的数据,连接数据库读取表中的数据。
    3. 针对文件系统中的数据,通过流读取文件系统的文件。

    以上技术中使用第一种较多,因为目前全文检索主要搜索数据的来源是互联网,在Internet上采集信息的软件通常称为爬虫或蜘蛛,也称为网络机器人,爬虫访问互联网上的每一个网页,将获取到的网页内容存储起来,所以搜索引擎使用一种爬虫程序抓取网页( 通过http抓取html网页信息)。 
    Lucene不提供信息采集的类库,需要自己编写一个爬虫程序实现信息采集,也可以通过一些开源软件实现信息采集,以下是一些爬虫项目(了解):

    • Solr(http://lucene.apache.org/solr),solr是apache的一个子项目,支持从关系数据库、xml文档中提取原始数据。
    • Nutch(http://lucene.apache.org/nutch), Nutch是apache的一个子项目,包括大规模爬虫工具,能够抓取和分辨web网站数据。
    • jsoup(http://jsoup.org/ ),jsoup是一款Java的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
    • Heritrix(http://sourceforge.net/projects/archive-crawler/files/),Heritrix是一个由java开发的、开源的网络爬虫,用户可以使用它来从网上抓取想要的资源。其最出色之处在于它良好的可扩展性,方便用户实现自己的抓取逻辑。

    本案例我们要获取磁盘上文件的内容,可以通过文件流来读取文本文件的内容,对于pdf、doc、xls等文件可通过第三方提供的解析工具读取文件内容,比如Apache POI读取doc和xls的文件内容。

    创建文档对象

    获取原始内容的目的是为了索引,在索引前需要将原始内容创建成文档(Document),文档中包括一个一个的域(Field),域中存储内容。 
    这里我们可以将磁盘上的一个文件当成一个Document,Document中包括一些Field(file_name文件名称、file_path文件路径、file_size文件大小、file_content文件内容),如下图: 
    这里写图片描述 
    注意:每个Document可以有多个Field,不同的Document可以有不同的Field,同一个Document可以有相同的Field(域名和域值都相同)。每个文档都有一个唯一的编号,就是文档id

    分析文档

    将原始内容创建为包含域(Field)的文档(Document),需要再对域中的内容进行分析,分析的过程是经过对原始文档提取单词、将字母转为小写、去除标点符号、去除停用词(没有意义的单词)等过程生成最终的语汇单元,可以将语汇单元理解为一个一个的单词。 
    例如,原始文档内容如下:

    Lucene is a Java full-text search engine. Lucene is not a complete 
    application, but rather a code library and API that can easily be used 
    to add search capabilities to applications.

    上边的文档经过分析得出的语汇单元为:

    lucene、java、full、search、engine……

    每个单词叫做一个Term,不同的域中拆分出来的相同的单词是不同的Term(同一个域中拆分出来的相同的单词是同一个Term)。Term中包含两部分内容,一部分是文档的域名,另一部分是单词的内容。 
    例如:文件名中包含的apache和文件内容中包含的apache是不同的Term。

    创建索引

    对所有文档分析得出的语汇单元进行索引,索引的目的是为了搜索,最终要实现只搜索被索引的语汇单元从而找到Document(文档)。 
    这里写图片描述 
    注意:创建索引是对语汇单元索引,通过词语找文档,这种索引的结构叫倒排索引结构。传统方法是根据文件找到该文件的内容,在文件内容中匹配搜索关键字,这种方法是顺序扫描方法,数据量大、搜索慢。 
    倒排索引结构是根据内容(词语)找文档,如下图: 
    这里写图片描述 
    倒排索引结构也叫反向索引结构,包括索引和文档两部分,索引即词汇表,它的规模较小,而文档集合较大

    查询索引

    查询索引也是搜索的过程。搜索就是用户输入关键字,从索引(index)中进行搜索的过程。根据关键字搜索索引,根据索引找到对应的文档,从而找到要搜索的内容(这里指磁盘上的文件)。

    用户查询接口

    全文检索系统提供用户搜索的界面供用户提交搜索的关键字,搜索完成展示搜索结果。比如: 
    这里写图片描述
    Lucene不提供制作用户搜索界面的功能,需要根据自己的需求开发搜索界面。

    创建查询

    用户输入查询关键字执行搜索之前需要先构建一个查询对象,查询对象中可以指定查询要搜索的Field文档域、查询关键字等,查询对象会生成具体的查询语法。例如,语法 “fileName:lucene”表示要搜索Field域的内容为“lucene”的文档。

    执行查询

    搜索索引过程:根据查询语法在倒排索引词典表中分别找出对应搜索词的索引,从而找到索引所链接的文档链表。例如,搜索语法为“fileName:lucene”表示搜索出fileName域中包含Lucene的文档。搜索过程就是在索引上查找域为fileName,并且关键字为Lucene的Term,并根据Term找到文档id列表。 
    这里写图片描述

    这里写图片描述
    索引域:索引域是用于搜索的,搜索程序将从索引域中搜索一个一个词,根据词找到对应的文档。之所以根据词可以找到文档,是因为词是从Document中的Field内容抽取出来的。将Document中的Field的内容进行分词,将分好的词创建索引,索引=Field域名:词(表示从Document中的哪个Field抽取的词)。

    渲染结果

    以一个友好的界面将查询结果展示给用户,用户根据搜索结果找自己想要的信息,为了帮助用户很快找到自己的结果,提供了很多展示的效果,比如搜索结果中将关键字高亮显示,百度提供的快照等。 
    这里写图片描述

    展开全文
  • solr全文检索实现原理

    万次阅读 多人点赞 2016-11-21 20:33:17
    solr那是我1年前使用到的一个搜索引擎,由于当初对于配置了相应了,但是今天突然面试问到了,哎,太久了,真的忘记了,今天特地写一篇博客记下来 solr是一个独立的企业级搜索应用服务器,它对外t提供类似于web-...

    solr那是我1年前使用到的一个搜索引擎,由于当初对于配置了相应了,但是今天突然面试问到了,哎,太久了,真的忘记了,今天特地写一篇博客记下来

    solr是一个独立的企业级搜索应用服务器,它对外t提供类似于web-service的api接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的xml文件,生成索引。;

    也可以通过http get操作提出查询的请求,得到xml/json格式的返回结果

    Lucene是一个高效的,基于Java的全文检索库。

    所以在了解Lucene之前要费一番工夫了解一下全文检索。

    那么什么叫做全文检索呢?这要从我们生活中的数据说起。

    我们生活中的数据总体分为两种:结构化数据非结构化数据

    • 结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。
    • 非结构化数据:指不定长或无固定格式的数据,如邮件,word文档等。

    当然有的地方还会提到第三种,半结构化数据,如XML,HTML等,当根据需要可按结构化数据来处理,也可抽取出纯文本按非结构化数据来处理。

    非结构化数据又一种叫法叫全文数据。

     

    按照数据的分类,搜索也分为两种:

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

    对非结构化数据也即对全文数据的搜索主要有两种方法:

    一种是顺序扫描法(Serial Scanning):所谓顺序扫描,比如要找内容包含某一个字符串的文件,就是一个文档一个文档的看,对于每一个文档,从头看到尾,如果此文档包含此字符串,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有的文件。如利用windows的搜索也可以搜索文件内容,只是相当的慢。如果你有一个80G硬盘,如果想在上面找到一个内容包含某字符串的文件,不花他几个小时,怕是做不到。Linux下的grep命令也是这一种方式。大家可能觉得这种方法比较原始,但对于小数据量的文件,这种方法还是最直接,最方便的。但是对于大量的文件,这种方法就很慢了。

    有人可能会说,对非结构化数据顺序扫描很慢,对结构化数据的搜索却相对较快(由于结构化数据有一定的结构可以采取一定的搜索算法加快速度),那么把我们的非结构化数据想办法弄得有一定结构不就行了吗?

    这种想法很天然,却构成了全文检索的基本思路,也即将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定结构,然后对此有一定结构的数据进行搜索,从而达到搜索相对较快的目的。

    这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引

    这种说法比较抽象,举几个例子就很容易明白,比如字典,字典的拼音表和部首检字表就相当于字典的索引,对每一个字的解释是非结构化的,如果字典没有音节表和部首检字表,在茫茫辞海中找一个字只能顺序扫描。然而字的某些信息可以提取出来进行结构化处理,比如读音,就比较结构化,分声母和韵母,分别只有几种可以一一列举,于是将读音拿出来按一定的顺序排列,每一项读音都指向此字的详细解释的页数。我们搜索时按结构化的拼音搜到读音,然后按其指向的页数,便可找到我们的非结构化数据——也即对字的解释。

       这种先建立索引,在对索引进行搜索的过程就叫做全文检索。

      全文检索大体分为2个过程,索引创建和搜索索引

     1.索引创建:将现实世界中的所有结构化和非结构化数据提取信息,创建索引的过程

     2.索引索引:就是得到用户查询的请求,搜索创建的索引,然后返回结果的过程

     于是全文检索就存在3个重要的问题:

     1. 索引里面究竟存了什么东西?

     2.如何创建索引?

     3.如何对索引进行搜索?

    下面我们顺序对每个个问题进行研究。

     

    二、索引里面究竟存些什么

    索引里面究竟需要存些什么呢?

    首先我们来看为什么顺序扫描的速度慢:

    其实是由于我们想要搜索的信息和非结构化数据中所存储的信息不一致造成的。

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

    由于从字符串到文件的映射是文件到字符串映射的反向过程,于是保存这种信息的索引称为反向索引

    反向索引的所保存的信息一般如下:

    假设我的文档集合里面有100篇文档,为了方便表示,我们为文档编号从1到100,得到下面的结构

     

    左边保存的是一系列字符串,称为词典

    每个字符串都指向包含此字符串的文档(Document)链表,此文档链表称为倒排表(Posting List)。

    有了索引,便使保存的信息和要搜索的信息一致,可以大大加快搜索的速度。

    比如说,我们要寻找既包含字符串“lucene”又包含字符串“solr”的文档,我们只需要以下几步:

    1. 取出包含字符串“lucene”的文档链表。

    2. 取出包含字符串“solr”的文档链表。

    3. 通过合并链表,找出既包含“lucene”又包含“solr”的文件。

     

    看到这个地方,有人可能会说,全文检索的确加快了搜索的速度,但是多了索引的过程,两者加起来不一定比顺序扫描快多少。的确,加上索引的过程,全文检索不一定比顺序扫描快,尤其是在数据量小的时候更是如此。而对一个很大量的数据创建索引也是一个很慢的过程。

    然而两者还是有区别的,顺序扫描是每次都要扫描,而创建索引的过程仅仅需要一次,以后便是一劳永逸的了,每次搜索,创建索引的过程不必经过,仅仅搜索创建好的索引就可以了。

    这也是全文搜索相对于顺序扫描的优势之一:一次索引,多次使用。

    三、如何创建索引

    全文检索的索引创建过程一般有以下几步:

    第一步:一些要索引的原文档(Document)。

    为了方便说明索引创建过程,这里特意用两个文件为例:

    文件一: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)。

    分词组件(Tokenizer)会做以下几件事情(此过程称为Tokenize):

    1. 将文档分成一个一个单独的单词。

    2. 去除标点符号。

    3. 去除停词(Stop word)。

    所谓停词(Stop word)就是一种语言中最普通的一些单词,由于没有特别的意义,因而大多数情况下不能成为搜索的关键词,因而创建索引时,这种词会被去掉而减少索引的大小。

    英语中挺词(Stop word)如:“the”,“a”,“this”等。

    对于每一种语言的分词组件(Tokenizer),都有一个停词(stop word)集合。

    经过分词(Tokenizer)后得到的结果称为词元(Token)。

    在我们的例子中,便得到以下词元(Token):

    “Students”,“allowed”,“go”,“their”,“friends”,“allowed”,“drink”,“beer”,“My”,“friend”,“Jerry”,“went”,“school”,“see”,“his”,“students”,“found”,“them”,“drunk”,“allowed”。

    第三步:将得到的词元(Token)传给语言处理组件(Linguistic Processor)。

    语言处理组件(linguistic processor)主要是对得到的词元(Token)做一些同语言相关的处理。

    对于英语,语言处理组件(Linguistic Processor)一般做以下几点:

    1. 变为小写(Lowercase)。

    2. 将单词缩减为词根形式,如“cars”到“car”等。这种操作称为:stemming。

    3. 将单词转变为词根形式,如“drove”到“drive”等。这种操作称为:lemmatization

    第四步:将得到的词(Term)传给索引组件(Indexer)。等等

    总而言之

    1. 索引过程:

    1) 有一系列被索引文件

    2) 被索引文件经过语法分析和语言处理形成一系列词(Term)。

    3) 经过索引创建形成词典和反向索引表。

    4) 通过索引存储将索引写入硬盘。

    2. 搜索过程:

    a) 用户输入查询语句。

    b) 对查询语句经过语法分析和语言分析得到一系列词(Term)。

    c) 通过语法分析得到一个查询树。

    d) 通过索引存储将索引读入到内存。

    e) 利用查询树搜索索引,从而得到每个词(Term)的文档链表,对文档链表进行交,差,并得到结果文档。

    f) 将搜索到的结果文档对查询的相关性进行排序。

    g) 返回查询结果给用户。


     

    展开全文
  • 全文检索的基本原理

    千次阅读 2018-08-17 23:58:23
    最近想要学习有关语义搜索的算法知识,听大神讲解了解到lucene全文搜索库,查阅了官网的说明和一些博客,将个人理解到的全文检索方法整理在下面。 一、首先,为什么需要全文搜索? 首先介绍两种数据分类,根据搜索...

    最近想要学习有关语义搜索的算法知识,听大神讲解了解到lucene全文搜索库,查阅了官网的说明和一些博客,将个人理解到的全文检索方法整理在下面。


    一、首先,为什么需要全文搜索?

    首先介绍两种数据分类,根据搜索内容格式不同,一般将搜索数据分为两类:

    1. 结构化数据指具有固定格式或有限长度的数据,如数据库、元数据等。针对结构化数据的搜索,例如对数据库的搜索,可以使用SQL语句。再如对元数据的搜索,例如windows中对文件名、类型和修改时间进行搜索等。

    2. 非结构化数据(全文数据)指不定长或没有固定格式的数据,例如邮件、word文档等。对非结构化数据的搜索,例如windows中对文件内容的搜索、Linux中grep命令,以及使用Google或百度来搜索内容都属于对全文数据的搜索。

    对结构化的数据,可以使用搜索算法按照结构较快地进行检索。

    但是对非结构化的数据,由于没有特定结构,因此在数据量比较小时,可以使用顺序扫描法,一个文件一个文件地找,找到包含检索字符串的文件。如windows文件搜索,Linux中grep命令。这样的方法对于数据量较小时比较直接,但是对于数据量较大的文件检索效率较低。

    因此有大神想到了一种办法,将非结构化的数据部分转化为结构化的数据,再对字符串进行检索,这样检索的效率就可以加快!那么,怎样将非结构化数据转化为部分结构化的数据呢?这个就是我们下面要提到的全文检索算法啦!

    由于已知的信息是文件中有哪些字符串,待求的问题是哪些文件包含字符串,因此需要保存字符串到文件的映射,所以也将这种索引称为反向索引。


    二、其次,啥叫全文检索?

    全文检索:将非结构化数据按照规则提取信息,重新组织,使其有一定结构(提取出用于重新组织的信息即为索引),对有一定结构的数据利用搜索算法加快检索速度。例如字典中将拼音作为索引进行排序。

    全文搜索的缺点:需要创建索引和搜索索引,对于数据量小的情况速度不一定比顺序检索快。优点:每次检索不需要重复创建索引的过程,一次创建索引,可以多次使用。


    三、全文搜索是怎么实现的?

    简而言之:先建立索引(indexing),再根据索引进行搜索(Search)。(啥,就一句话?哈哈不急,下面了解一下这句话的详细步骤吧)

    1. 下面首先了解一下索引是怎么创建的吧(啥?索引是啥,可以吃嘛?)。首先了解一下什么是索引:

    索引图示:

    上面这张图中,左边是待查找的字符串,称为词典,右边是每个字符串指向的文件链表,称为倒排表。

    2. 索引是怎么创建的呢?(咦,这个标题怎么和上面一样?)

    要把索引创建好,主要分3步:

    第一步:将文档传递给分词组件(Tokenizer),由分词组件根据标点符号和停词(没有语义的词,通常不会作为检索关键词,可以作为单词的分隔符,例如英文中a或the等),将文档分为一个个单独的单词。经过分词后得到的结果称为词元(Token)。

    第二步:将得到的词元传给语言处理组件进行语言处理(将单词处理为词根,如将英文去除复数后缀s,形容词去除nal(可以根据固定算法进行缩减),以及将时态转换为现在式(根据字典知识)。语言处理组件处理后的结果称为词(Term)。

    第三步:将得到的词(Term)传递给索引组件(Indexer),索引组件先将得到的词创建为字符串与文档ID的映射词典,接着对字符串按字母顺序排序,合并相同的字符串,最后形成一张文档倒排链表(如下所示):其中Document Frequency表示几个文档中包含这个单词,Frequency表示编号为Document ID的文档包含了几个Term单词。

    3. 创建好索引以后,怎么用索引来搜索呢?

    要想根据索引查找到文件名,主要也分3步:

    第一步:用户输入查询语句(有一定语法:AND/OR/NOT);对查询语句进行词法分析(区分单词与关键字AND/OR/NOT)、语法分析(根据查询到的单词与关键词形成如下的语法树)及语言处理(将不同形式的单词转换为词根);

    第二步:搜素索引,得到符合条件的文档;根据相关性对结果进行排序。

    第三步:计算相关性:对相关性进行打分,分数越高越靠前。这里需要找到哪些词对文档的关系最重要(关键词),再判断两个文档间关键词的相似度。找到词对于文档的重要性就是计算词的权重。词的权重表示词再文档中的重要程度,权重越大的单词在计算文档的相关性中作用越大。

    第四步:根据词的权重来进行结果排序:运用向量空间模型算法(VSM)通过词之间的关系得到文档相关性。

    4. 没啦?上面那个向量xx算法,这是个啥?还有,词的权重是咋计算出来的呢?

    首先,计算词的权重:

    咋上来就是公式,好好说人话!

    上面的公式里,tf表示词在一个文档中出现次数tf(Term Frequency)越大,词越重要;出现该次的文档数df(Document Frequency)越大,词越不重要。

    接下来,将查询文档所有词放在一个向量中(Document Vector),将查询语句所有词放在一个向量中(Query Vector),将两个向量维数取并集(并集维数为N),产生一个N维空间,每个词是一维,通过向量夹角的余弦值计算两个向量之间的夹角,余弦值越小,说明两向量之间夹角越小,说明查询结果的打分越高,相关性越大。具体相关性打分公式如下:


    四、结语

    用官网文档中的流程图来总结上面的步骤(此图参照http://www.lucene.com.cn/about.htm中文章《开放源代码的全文检索引擎Lucene》):

    具体文字的流程是下面这样的:

    1. 建立索引的过程:
      1. 有一系列被索引文件
      2. 被索引文件经过语法分析和语言处理形成一系列词(Term)
      3. 经过索引创建形成词典和反向索引表
      4. 通过索引存储将索引写入硬盘
    2. 搜索过程:
      1. 用户输入查询语句。
      2. 对查询语句经过语法分析和语言分析得到一系列词(Term)
      3. 通过语法分析得到一个查询树
      4. 通过索引存储将索引读入到内存
      5. 利用查询树搜索索引,从而得到每个词(Term)的文档链表,对文档链表进行交,差,并得到结果文档
      6. 将搜索到的结果文档对查询的相关性进行排序
      7. 返回查询结果给用户。
    展开全文
  • 全文检索概念介绍

    千次阅读 2017-08-18 15:15:48
    1.全文检索概念介绍  今天小编给大家讲解全文搜索的概念,希望大家对全文搜索能够有一个整体的了解。 1.1我们身边的搜索 l 在BBS、BLOG、新闻等系统中提供的搜索文章的功能,如这里的贴吧的例子。搜索的范围是系统...
  • 》 官网 ...》 Lucene的全文检索是指什么: 程序扫描文档,对文档document建立索引,并对文档进行分词 ik,对每一个词建立索引并关联文档document的编号(索引); 当用户进行搜索时候,按照搜...
  • 索引的概念     索引在生活中存在方方面面的应用。比如你去超市,超市把商品分了不同的区间,日用平、生鲜、粮油、饮料等等,比如你去买可乐,直接去立着饮料牌子的区间去找就可以,不用去挨着...
  • 全文检索&倒排索引

    千次阅读 2018-01-30 11:11:55
    全文检索&倒排索引 设计 全文检索 建立索引,快速定位搜索 倒叙索引 分词 根据分词来定位
  • 倒排索引与全文检索

    2020-10-21 20:14:07
    倒排索引 一个未经处理的数据库中,一般是以文档ID作为索引,文档内容作为记录 而倒排索引指的是,将单词或记录作为索引,将文档ID作为记录,...haystack是django的开源搜索框架,该框架支持 Solr,Elasticsearch,Wh
  • 全文检索就比较好理解的,就是当我们输入“全瓦解”,会被拆分成”全”,“瓦解”2个此,用2个词去倒排索引里面去检索数据,检索到的数据返回。整个过程就叫做全文检索 lucene:就是一个jar包,里面包含了封装好的...
  • 1、什么是全文检索

    千次阅读 2016-12-13 11:21:23
    1.1结构化数据和非结构化数据我们生活中的数据总体分为两种:结构化数据和非结构化数据。 · 结构化数据:指具有固定格式...再如对元数据的搜索,如利用windows搜索对文件名,类型,修改时间进行搜索等。1.3对非结...
  • 全文检索技术

    千次阅读 热门讨论 2019-06-25 08:17:56
    什么是全文检索 全文数据库是全文检索系统的主要构成部分。所谓全文数据库是将一个完整的信息源的全部内容转化为计算机可以识别、处理的信息单元而形成的数据集合。全文数据库不仅存储了信息,而且还有对全文数据...
  • 最近遇到有些人对于 SQL Server Express有些小误解,误会大部分起源于SQL Server Express是免费的,所以不包含很多专业版的功能(尤其集中在对于不包含全文检索的误会)SQL Server 2008 Express Edition应该再区分为...
  • 应用场景酒店预订app全文检索具体实现1、 根据业务组建查询条件参数:SearchParams2、构建关键字查询:keywordQuery/** * 构建关键字查询。 * * 从多个字段构建关键字查询,包括拼音。 * * @param keyword ...
  • 全文检索首先对要搜索的文档进行分词,然后形成索引,通过查询索引来查询文档。全文检索是目前搜索引擎,大数据搜索的关键技术。全文检索系统可实现亚秒级的检索速度以及每秒上百次的并发检索支持。 需求: 实现...
  • 全文检索

    万次阅读 2017-11-30 09:10:29
    现在请你编写一个简单的全文检索程序。  问题的描述是这样的:给定一个信息流文件,信息完全有数字组成,数字个数不超过60000个,但也不少于60个;再给定一个关键字集合,其中关键字个数不超过10000个,每个关键字...
  • 全文检索技术Lucene

    千次阅读 2018-11-02 21:10:04
    Lucene 是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。说到底它是一个信息检索程序库,而不是应用产品...
  • 全文检索框架Lucene——原理

    千次阅读 2015-09-06 16:26:18
    Lucene 是一个高效的,基于Java 的全文检索库。 所以在了解Lucene之前要费一番工夫了解一下全文检索。 那么什么叫做全文检索呢?这要从我们生活中的数据说起。 我们生活中的数据总体分为两种:结构化数据 和非...
  • 如何使用PHP实现全文检索功能? 很多人可能马上可以想出几种方案,比如:文件检索法、采用SQL的like语句等方法,但这些方法效率都相当的低。 这里介绍一种比较高效的PHP全文检索实现方法,这就是采用MYSQL的FULLTEXT...
  • MySQL 全文检索

    2017-06-27 10:26:34
    MySQL 全文检索支持MySQL 全文检索支持 MyISAM 40以上 InnoDB564以上 全文检索语法 检索方式 简单示例 MySQL全文索引相关配置 注意事项 MyISAM (4.0以上)从MySQL 4.0以上 myisam引擎就支持了full text search 全文...

空空如也

1 2 3 4 5 ... 20
收藏数 136,708
精华内容 54,683
关键字:

全文检索