学习目标:ES +spark mlib
提示:这里可以添加学习目标
例如:ES 海量数据搜索原理
ES原理:
例如:
1、 Elasticsearch概念
Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎 Apache Lucene™ 基础上的搜索引擎.当然 Elasticsearch 并不仅仅是 Lucene 那么简单,它不仅包括了全文搜索功能,还可以进行以下工作:
分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索。
实时分析的分布式搜索引擎。
Elasticsearch是面向文档型数据库,一条数据在这里就是一个文档,用JSON作为文档序列化的格式,比如下面这条用户数据:
{
“name” : “John”,
“sex” : “Male”,
“age” : 25,
“birthDate”: “1990/05/01”,
“about” : “I love to go rock climbing”,
“interests”: [ “sports”, “music” ]
}
可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。
2、 ES文件存储和关系型数据库的对比
用Mysql这样的数据库存储就会容易想到建立一张User表,在Elasticsearch里这就是一个文档,当然这个文档会属于一个User的类型,各种各样的类型存在于一个索引当中。这里有一份简易的将Elasticsearch和关系型数据术语对照表:
关系数据库 ⇒ 数据库 ⇒ 表 ⇒ 行 ⇒ 列(Columns)
Elasticsearch ⇒ 索引(Index) ⇒ 类型(type) ⇒ 文档(Docments) ⇒ 字段(Fields)
3、*新版的ES对Index以及Type 已经不做区分
关系型数据库 | ES对比 |
---|---|
database | index |
table | type |
row | document |
column | Field |
schema | Mapping |
Index | everything is Index |
SQL | Query DSL |
Select* from table…… | GET http…… |
update table SET | put http |
索引:(1)搜索中的数据库或者表定义 (2)构建文档的时候索引创建
实质上,搜索是以词为单位做最基本的搜索单元。依靠分词器构建分词。最后用分词构建倒排索引。
- ES 搜索的过程
搜索是以词为单位做基本的搜索单元,依靠分词器构建分词,用分词构建倒排索引。
对比正向索引和倒排索引发现,正向索引是通过检索每一个文档中包含的搜索关键字。这种方式需要便利所有的文档。倒排索引则是经过分词后的token查询出包含该词的文档。相比于正常索引倒排索引更加高效。
语法规则
// 非结构化新建索引
delete /employee
put /employee/_doc/1
{
"name":"小明",
"age":30
}
PUT /employee
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
}
}
GET /employee/_doc/1
// 指定字段修改
POST /employee/_update/1
{
"doc":{
"name":"小明2"
}
}
//强制指定创建,若已经存在则失败
POST /employee/_create/1
{
"name":"小明3",
"age":25
}
// 删除某个文档
DELETE /employee/_doc/2
// 查询全部文档
GET /employee/_search
// 使用结构化的方式创建索引
PUT /employee
{
"settings": {"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"name":{
"type":"text"
},
"age":{
"type": "integer"
}
}
}
}
// 不带条件查询所有记录
GET /employee/_search
{
"query": {
"match_all": {}
}
}
// 分页查询
GET /employee/_search
{
"query": {
"match_all": {}
},
"from":0,
"size":2
}
// 关键字查询 默认按照中文分词器进行分词查询
GET /employee/_search
{
"query": {
"match": {
"name": "小明"
}
}
}
GET /employee/_search
{
"query": {
"match": {
"name": "杰"
}
},
"sort":[
{"age":{"order":"desc"}
}
]
}
如图所示当我们按照业务逻辑打分时 这个score字段将变得没有意义,是按照sort的规则进行的排序。
// 带聚合操作 terms表示在词纬度进行聚。field表示具体的聚合字段。
GET /employee/_search
{
"query": {
"match": {"name":"明"
}
},
"sort":[
{"age":{
"order":"desc"
}
}
],
"aggs":{
"group_by_age":{
"terms": {
"field":"age"
}
}
}
}
可以看到在原来查询的基础上计算了以age作为聚合的词出现的数量
ES高级语法:
analyze 分析过程实质上等同于分词的过程.
标准分词器: 关键词->(字符过滤器)->以空格和标点符号分割内容->小写转换
English分词器:关键词->(字符过滤器,量词,the等)->以空格和标点符号分割内容->分词过滤(分词转换、词干抽取)
// 使用结构化的方式创建索引
PUT /movie
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"name":{"type":"text","analyzer": "english"}
}
}
}
GET /movie/_search
GET /movie/_search
{
"query": {
"match": {
"name": "eat"
}
}
}
不使用分词器则默认为标准分词器
PUT /movie/_doc/1
{
"name":"Eating an apple a day & Keeps the doctor away"
}
GET /movie/_search
{
"query": {
"match": {
"name": "eat"
}
}
}
查询发现英文分词器更加符合预期。
相关性查询手段
Tmdb实例
ES的高性能:
提示:这里可以添加计划学习的时间
为了提高搜索的性能,难免会牺牲某些其他方面,比如插入/更新,否则其他数据库不用混了。前面看到往Elasticsearch里插入一条记录,其实就是直接PUT一个json的对象,这个对象有多个fields,比如上面例子中的name, sex, age, about, interests,那么在插入这些数据到Elasticsearch的同时,Elasticsearch还默默1的为这些字段建立索引–倒排索引,因为Elasticsearch最核心功能是搜索。
Query dsl:
match查询按照字段的分词分析后 去索引中进行查询
而term查询则是精准匹配
es检索排序
ES 是按照查询和文档的相关度进行排序的。默认是按照评分降序排序。
TF-IDF 算法 (Term Frequency -Inverse Document Frequency) 是一种用于信息检索与文本挖掘的常用加权算法。用于评估一个词对于语料库中一个文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加单同时会随着它在文件中出现的频率成反比下降。
词频(Term Frequency)
是指某一单词(Term)的频率Frequency。这次使用频率而不是次数,是为了防止文档内容过长从而导致某些单词出现的次数过多。为了正确评价一个单词在文件中出现的重要程度需要将出先次数归一化。
t
f
i
=
n
i
/
∑
n
=
1
N
k
n
tf_i=n_i/\sum_{n=1}^Nk_n
tfi=ni/n=1∑Nkn
逆向文档频率(Inverse Document Frequency) 逆向文档频描述的对象是一个文档集合中,包含某个单词的文档数量,一个单词在一个文档集合中的普遍重要程度。归一化算法
i
d
f
i
=
l
g
∣
D
∣
1
+
∣
j
:
t
i
ϵ
d
j
∣
idf_i = lg\frac{\left | D \right |}{1+\left | j:t_i\epsilon d_j \right |}
idfi=lg1+∣j:tiϵdj∣∣D∣
∣
D
∣
表
示
文
档
集
合
中
的
文
件
总
数
{\left | D \right |}表示文档集合中的文件总数
∣D∣表示文档集合中的文件总数
∣
j
:
t
i
ϵ
d
j
∣
{\left | j:t_i\epsilon d_j \right |}
∣j:tiϵdj∣
表示包含t_i的文件数。如果词语不在文件集中就导致分母为0
因此一般情况会在分母加1
最后
t
f
i
d
f
i
=
t
f
i
∗
i
d
f
i
tfidf_i = tf_i*idf_i
tfidfi=tfi∗idfi
也就是说某一特定文件的高频词语以及该词语在整个文件集合中的低文件频率(说明这个词有较高的区分度)可以产生出搞权重的TF-IDF。
Okapi BM25 算法原理:
IF-IDF 作为基于统计学的算法是一个可用算法但是它并不完美。在多频文档内容长度不同对TF的计算结果影响很大。
∑
i
=
1
n
I
D
F
(
q
i
)
⋅
f
(
q
i
,
D
)
⋅
(
k
i
+
1
)
f
(
q
i
,
D
)
+
k
i
⋅
(
1
−
b
+
b
⋅
∣
D
∣
a
v
g
(
d
l
)
)
\sum_{i=1}^{n} IDF(q_i) \cdot \frac{f(q_i,D)\cdot (k_i+1)}{f(q_i,D)+k_i\cdot (1-b+b\cdot \frac{\left | D \right |}{avg(dl)})}
i=1∑nIDF(qi)⋅f(qi,D)+ki⋅(1−b+b⋅avg(dl)∣D∣)f(qi,D)⋅(ki+1)
Q表示文档集合
D具体文档
I
D
F
(
q
i
)
表
示
T
F
−
I
D
F
中
q
i
在
文
档
中
的
T
F
值
IDF(q_i)表示TF-IDF中q_i在文档中的TF值
IDF(qi)表示TF−IDF中qi在文档中的TF值
f
(
q
i
,
D
)
表
示
q
i
在
D
中
的
T
F
值
∣
D
∣
为
文
本
长
度
f(q_i,D)表示q_i在D中的TF值 |D|为文本长度
f(qi,D)表示qi在D中的TF值∣D∣为文本长度
Ki 词频饱和度一般介于1.2到2.0之间,数值越低则饱和度越快。ES中为1.2
a
v
g
d
l
文
本
平
均
长
度
avgdl文本平均长度
avgdl文本平均长度
b为字段规约长度,相当于将文档的长度规约化到全部文档的平均长度。它的值在0-1之间。1意味着全部规约化,0表示不规约。在es中的值取0.75