Skip to main content

全文搜索

全文搜索

  • Lucene

  • Solr

  • ElasticSearch

db层索引: 非结构化数据,只能全文扫描

因此需要特殊索引:从值反向定位在哪个文档哪行,反向索引

  • Parser:解析数据,数据可能是html、pdf、word文档,使用相关的parser解析
  • Analysis:分析token,比如有些单词是take、took、taken都是take的不同形式,需要做一个归类
  • 然后根据规则,建立索引,这样就可以根据索引查询了
  1. keyword => {doc}

  2. Ordering:相似度,频率,......

  3. index => field

  4. 更新,增量式维护

IR 信息获取工具

高效交叉索引

query => index <- adapter <- origin file/web/db/...

衡量指标:

  • 精度
  • 召回率
  • 速度

读入:Analyzer -> Tokenizer -> Tokenfilter -> StopAnalyzer -> Encode/Decode

建索引/存储

Field
  • 每个字段对应于在搜索期间根据索引查询或从索引检索的一段数据。
  • Keyword:关键字不被分析(就是不会被拆开),而是被索引并逐字存储在索引中。
  • UnIndexed:既不分析也不索引,但其值按原样存储在索引中。也就是说一旦假如通过keyword查询到了,要把unindex的部分的内容要带出来,但是这部分不索引。
  • UnStored:此字段类型被分析和索引,但不存储在索引中。当然他有一些停用词列表,比如都共有的词。一般是正文,非常长不应该存在索引里面,非常浪费。
  • Text:被分析并被索引,存储到索引里面。这意味着可以针对这种类型的字段进行搜索,但要注意字段大小。可以类比keyword,区别是这个text会被分析一下,而keyword不会
  • 综上,以上field保证索引的大小!

Solr 和 MySQL 的 FULLTEXT 索引都使用了倒排索引(Inverted Index)的结构来实现全文搜索。

倒排索引结构

倒排索引的核心由两部分组成:

  1. 词项字典 (Term Dictionary): 存储所有文档中出现的唯一词项,通常按照字母顺序排序,以便快速查找。
  2. 倒排列表 (Posting List): 对于词项字典中的每个词项,都有一个对应的倒排列表。这个列表记录了包含该词项的所有文档 ID,以及一些附加信息,例如词项在文档中出现的频率 (Term Frequency, TF)、词项在文档中出现的位置等等。 有些实现还会存储词项在文档中的偏移量,以便支持短语搜索。

为什么倒排索引能够支持全文搜索?

倒排索引之所以能够高效地支持全文搜索,主要是因为以下几个原因:

  1. 快速定位包含特定词项的文档: 通过词项字典,可以快速找到包含某个词项的倒排列表。倒排列表直接存储了包含该词项的文档 ID,避免了逐个文档扫描的开销。
  2. 易于进行布尔运算: 对于包含多个关键词的查询,可以通过对多个倒排列表进行交集、并集等布尔运算,快速得到满足查询条件的文档集合。例如,搜索 "brown fox",只需要获取 "brown" 和 "fox" 的倒排列表,然后取交集,即可找到同时包含这两个词项的文档 1。
  3. 支持更高级的搜索功能: 通过在倒排列表中存储额外的信息,例如词频、位置等,可以支持更高级的搜索功能,例如短语搜索、基于相关度的排序等。

MySQL FULLTEXT 索引 和 Solr 的区别

虽然 MySQL 的 FULLTEXT 索引和 Solr 都使用了倒排索引,但它们之间还是存在一些区别:

  • 功能丰富程度: Solr 作为一个专业的搜索引擎,提供了比 MySQL FULLTEXT 索引更丰富的功能,例如分词、拼写检查、高亮显示、faceted search 等。
  • 可扩展性: Solr 具有更好的可扩展性,可以处理更大规模的数据和更高的查询负载。
  • 更新机制: MySQL 的 FULLTEXT 索引通常与数据库事务绑定,更新索引会影响数据库性能。Solr 的索引更新机制更加灵活,可以进行增量更新,对数据库性能影响较小。