基本概念
Lucene: Lucene由Doug Cutting开发, Hadoop和Nutch也是出自他之手。
Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene™ 基础之上。Lucene 仅仅只是一个库,为了充分发挥其功能,你需要使用 Java 并将 Lucene 直接集成到应用程序中。Elasticsearch 不仅仅是 Lucene,并且也不仅仅只是一个全文搜索引擎。 Elasticsearch可以被下面这样准确的形容:
一个分布式的实时文档存储,每个字段可以被索引与搜索。
一个分布式实时分析搜索引擎。
能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据。
Elastic Search基本术语
Index: 名词的时候,是相当于关系型的数据库。
Index: 做动词时索引一个文档 就是存储一个文档到一个 索引 (名词)中以便被检索和查询
Type: 相当于表
Document: 相当于行记录
Doc id:相当于关系型数据的主键
倒排索引:一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表
倒排索引介绍
正向索引如下表
doc id | contents |
1 | quick search for test. |
2 | I am from China. |
3 | Let us go home, China is great |
倒排索引如下(分词是基于standard,ES版本是6.8.5):
Term dic | Posting IDS |
quick | 1 |
search | 1 |
for | 1 |
test | 1 |
I | 2 |
am | 2 |
from | 3 |
china | 2,3 |
let | 3 |
us | 3 |
go | 3 |
home | 3 |
great | 3 |
精确搜索
结构化搜索(Structured search) 是指有关探询那些具有内在结构数据的过程。比如日期、时间和数字都是结构化的:它们有精确的格式,我们可以对这些格式进行逻辑操作。比较常见的操作包括比较数字或时间的范围,或判定两个值的大小。
文本也可以是结构化的。比如用户的member type,分为gust,register.
在结构化查询中,我们得到的结果 总是 非是即否,要么存于集合之中,要么存在集合之外。结构化查询不关心文件的相关度或评分;它简单的对文档包括或排除处理。
全文搜索
根据文本搜索文档。比如搜索“ctrip”在不在一段话中。搜索的过程中,首先会涉及到对query分词,query分词后,会根据相关性返回top n的数据。
相关性(Relevance)
它是评价查询与其结果间的相关程度,并根据这种相关程度对结果排名的一种能力,这种计算方式可以是 TF/IDF 方法、地理位置邻近、模糊相似,或其他的某些算法。
检索词频率
检索词在该字段出现的频率?出现频率越高,相关性也越高。 字段中出现过 5 次要比只出现过 1 次的相关性高。
反向文档频率
每个检索词在索引中出现的频率?频率越高,相关性越低。检索词出现在多数文档中会比出现在少数文档中的权重更低。
字段长度准则
字段的长度是多少?长度越长,相关性越低。 检索词出现在一个短的 title 要比同样的词出现在一个长的 content 字段权重更大。
分析(Analysis)
它是将文本块转换为有区别的、规范化的 token 的一个过程,(参见 分析的介绍) 目的是为了(a)创建倒排索引以及(b)查询倒排索引。
FST简介
Lucene倒排索引中的核心数据结构是FST。FSA只有状态,FST是在FSA的基础上,增加了输出值. FST构造过程演示:http://examples.mikemccandless.com/fst.py?terms=&cmd=Build+it%21
FST,treeMap,HashMap比较
500万数据,比较的是构建和获取所有key的时间
HashMap | TreeMap | FST | |
build(ms) | 4316 | 5585 | 3974 |
get all(ms) | 379 | 1207 | 1945 |
object size(byte) | 625554536 | 631999248 | 768 |
HashMap
public void test_HashMap() {
HashMap<String, Integer> hashMap = new HashMap<>();
List<String> list = new ArrayList<>();
for (int i=0; i<5000000; i++) {
list.add("test"+i+"ab");
}
long time1 = System.currentTimeMillis();
for (int i=0; i<5000000; i++) {
hashMap.put(list.get(i), i);
}
long time2 = System.currentTimeMillis();
System.out.println("time elapsed for hash map: " + (time2-time1));
long time3 = System.currentTimeMillis();
for (int i=0; i<5000000; i++) {
hashMap.get(list.get(i));
}
long time4 = System.currentTimeMillis();
System.out.println("time elapsed for hash map iterator all: " + (time4-time3));
long sizeOfType = ObjectSizeCalculator.getObjectSize(hashMap);
System.out.println("memory occupied for hash map: " + sizeOfType);
}
TreeMap测试
public void test_TreeMap() {
TreeMap<String, Integer> treeMap = new TreeMap<>();
List<String> list = new ArrayList<>();
for (int i=0; i<5000000; i++) {
list.add("test"+i+"ab");
}
long time1 = System.currentTimeMillis();
for (int i=0; i<5000000; i++) {
treeMap.put(list.get(i), i);
}
long time2 = System.currentTimeMillis();
System.out.println("time elapsed for tree map: " + (time2-time1));
long time3 = System.currentTimeMillis();
for (int i=0; i<5000000; i++) {
treeMap.get(list.get(i));
}
long time4 = System.currentTimeMillis();
System.out.println("time elapsed for tree map iterator all: " + (time4-time3));
long sizeOfType = ObjectSizeCalculator.getObjectSize(treeMap);
System.out.println("memory occupied for tree map: " + sizeOfType);
}
FST测试
public void test_FST() {
try {
String inputValues[] = new String[5000000];
Long outputValues[] = new Long[5000000];
List<String> list = new ArrayList<>();
for (int i=0;i<5000000; i++) {
list.add("test"+i+"ab");
}
Collections.sort(list);
for (int i=0; i<5000000; i++) {
inputValues[i] = list.get(i);
outputValues[i] = new Long(i+1);
}
long time1 = System.currentTimeMillis();
PositiveIntOutputs outputs = PositiveIntOutputs.getSingleton();
Builder builder = new Builder(FST.INPUT_TYPE.BYTE1, outputs);
IntsRefBuilder intsRefBuilder = new IntsRefBuilder();
for (int i = 0; i < inputValues.length; i++) {
BytesRef scratchBytes = new BytesRef(inputValues[i]);
builder.add(Util.toIntsRef(scratchBytes, intsRefBuilder), outputValues[i].longValue());
}
FST fst = builder.finish();
long time2 = System.currentTimeMillis();
System.out.println("time elapsed for FST: "+(time2-time1));
long time3 = System.currentTimeMillis();
for (int i=0; i<5000000; i++) {
Util.get(fst, new BytesRef(inputValues[i]));
}
long time4 = System.currentTimeMillis();
System.out.println("time elapsed for FST iterator all: "+(time4-time3));
long sizeOfType = ObjectSizeCalculator.getObjectSize(fst);
System.out.println("memory occupied for fst: " + sizeOfType);
} catch (Exception e) {
;
}
}