01 ES 是什么
Elastic是一个基于Lucene的搜索引擎. 提供了具有HTTP Web和无架构JSON文档的分布式,多租户能力的全文搜索引擎.
- Elasticsearch是一款强大的开源搜索引擎,可帮助我们从海量数据中快速找到需要的内容.
- 开源分布式搜索引擎, 可用来实现搜索 日志统计 分析 系统监控等功能
Elasticsearch(负责存储 计算 搜索 分析数据)结合kibana(数据可视化) Logstash Beats(数据抓取),也就是elastic stack(ELK). 被广泛应用日志数据分析,实时监控
02 ES 特点
- 分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索。分发是实时的,被叫做”Push replication”
- 实时分析的分布式搜索引擎。
- 可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。
- Elasticsearch 完全支持 Apache Lucene 的接近实时的搜索。
- 处理多租户(multitenancy)不需要特殊配置,而Solr则需要更多的高级设置。
- Elasticsearch 采用 Gateway 的概念,使得完备份更加简单。
- 各节点组成对等的网络结构,某些节点出现故障时会自动分配其他节点代替其进行工作。
03 分词 与 倒排索引 与字典树
分词是给检索用的. ( IK 分词器).
英文,一个单词一个词, 词之间空格分隔
汉字,有各种各样分词器,一个强调效率,一个强调准确率. 比如 ‘使用户放心’,使用,户vs使,用户
倒排索引 举例:从文档内容找文档(通过搜索引擎)
传统的我们的检索是通过文章,逐个遍历找到对应关键词的位置。
而倒排索引,是通过分词策略,形成了词和文章的映射关系表,这种词典+映射表即为倒排索引。
有了倒排索引,就能实现 o(1)时间复杂度 的效率检索文章了,极大的提高了检索效率。
倒排索引,相反于一篇文章包含了哪些词,它从词出发,记载了这个词在哪些文档中出现过,由两部分组成——词典和倒排表。
加分项 :倒排索引的底层实现是基于:FST(Finite State Transducer)数据结构。
lucene 从 4+版本后开始大量使用的数据结构是 FST。FST 有两个优点:
1、空间占用小。通过对词典中单词前缀和后缀的重复利用,压缩了存储空间;
2、查询速度快。O(len(str))的查询时间复杂度。
:::info
**有限状态自动机(Finite State Transducer,FST)**是一种常见的字典数据结构,常用于NLP中。它可以表示一组字符串集合,并提供一种有效的方法来在这些字符串上执行查询操作。
FST 可以用于多种不同的任务,包括词形变化、拼写纠正、文本匹配和词义消歧等。
:::
数据结构 | 优缺点 | 相关代码 |
---|---|---|
ArrayList…… | 二分法查找,不平衡 | list.add(“”) |
Map…… | 内存消耗大 | map.put(“”,“”) |
Trie | 中文领域过于消耗内存 | TrieChineseTokenizer.java |
Double Array Trie | 相比于Trie,更适合中文,缺点是无法动态增删 | darts-java扩展 |
AhoCorasickDoubleArrayTrie | 存储大辞典时溢出 | AhoCorasickDoubleArrayTrie |
Finite State Transducers (FST) | Lucene中大量应用,本文重点说明 | FST.java |
- 针对ArrayList、Map这两个基本数据结构,不做过多介绍,直接跳过。
- 针对Trie这个数据结构,他更适合于英文,并不适合应用于中文环境。
- 中文文本中的字符集非常大,超过了 ASCII 字符集。Trie 数据结构在处理大字符集时,需要存储大量的节点,这会导致空间消耗变得非常大。
- 中文文本中的词汇组合非常灵活。中文中的词汇不像英文那样明确定义,并且同一个词可以有多种不同的组合方式。
- Trie数据结构在中文文本中,由于其空间和时间效率的限制以及中文文本的复杂性,可能不是最佳选择。
- 双数组Trie树是一种基于Trie树的数据结构
- DAT 的静态构建是通过将 Trie 树转换为两个数组实现的。其中一个数组存储 Trie 树中的节点信息,另一个数组则存储节点的孩子节点信息。这种实现方式具有很好的压缩性和查找效率。
- 当需要删除 Trie 树中的一个节点时,需要将该节点从 Trie 树中删除,并且可能需要对其祖先节点进行修改,以确保删除后的 Trie 树仍然是一棵有效的树。因为 DAT 中的数组是静态分配的,因此删除节点和修改数组可能会破坏原始数据结构的完整性,导致无法保证查找的正确性。
- AhoCorasickDoubleArrayTrie
- 在实际的应用中,存储大辞典的话,会出现溢出情况,并且在issues中也有他人出现这种问题。
- 重点实现 FST 数据机构,详见下面代码
- 使用语料库分别加入 AhoCorasickDoubleArrayTrie 和 FST,前者出现溢出情况(400w数据量左右),后者正常使用。
- 可以动态增删关键词
import java.io.Serializable;
import java.util.HashMap;
/**
* FST
*/
public class FST implements Serializable {
private HashMap<Character, FST> transitions = new HashMap<>();
private boolean isFinalState = false;
public void addWord(String word) {
if (word.isEmpty()) {
isFinalState = true;
return;
}
char c = word.charAt(0);
FST nextState = transitions.get(c);
if (nextState == null) {
nextState = new FST();
transitions.put(c, nextState);
}
nextState.addWord(word.substring(1));
}
public boolean isWord(String word) {
if (word.isEmpty()) {
return isFinalState;
}
char c = word.charAt(0);
FST nextState = transitions.get(c);
if (nextState == null) {
return