一. Term(词语)查询与全文查询
term的重要性:term是表达语义的最小单位,语言模型进行自然语言处理的时候都需要用到term
1.1 term查询
把文档插入索引的时候,默认会对字段做分词操作,就是Character — tokenizer—–fliter的切词处理,默认的是将非符号去除,然后空格分词,最后小写转入索引
所以在做term查询的时候,要查小写的value值,如果想精确匹配的话需要添加keyword的属性,es在插入索引的时候默认都会给每个字段添加一个多字段的keyword的属性
1
2
3
4
5
6
7
8
9
POST /INDEX/_search{
"query":{
"term":{
"字段名.keyword":{
"value":"精确字符,可包含大写与非数字"
}
}
}
}
1.2 复合查询-忽略算分
将query转成filter,忽略TF-DF计算, 避免相关性算分的开销
1
2
3
4
5
6
7
8
9
10
11
12
13
POST /index/_search
{
"explain":true,
"query":{
"constant-score":{
"filter":{
"term":{
"字段名.keyword":"真正的value"
}
}
}
}
}
1.3 全文本查询
基于全文本的查询有, match query / match phase query / query string query
特点
- 索引和搜索的时候都会进行分词操作,查询字符串先传递一个合适的分词器,然后生成一个供查询的词项列表
- 查询的时候也会对输入的查询进行分词操作, 然后逐个进行底层查询,最终将结果进行合并,为每个文档生成一个算分
二. 结构化查询
2.1 什么是结构化数据?
结构化查询指的是对结构数据的查询。日期, 布尔类型和数字都是结构化的数字。
文本也可以是结构化的
- 如彩色笔可以有离散的颜色集合:红,绿,蓝
- 一个博客被标记的标签:分布式,搜索, 大数据
2.2 常用场景
布尔,时间,日期和数字这类的结构化数据,有精确的格式, 我们可以对这些格式进行逻辑操作,包括比较数字或时间的范围,或判定范围值的大小
结构化数据可以用term做精确搜索或者部分匹配。term查询,prefix前缀查询
2.3 结构化查询种类
这些查询都可以通过constant score 转filter的形式避免算分
- 布尔查询
- range查询,数字range,日期range
- exists查询
- 多值字段查询,指的是一个字段中的值是一个数组。term查询是这个字段中的值包含这个数组的值的时候就判定符合,并不是一个精确查询,这种要做精确查询一般的解决方案是靠应用层在写数据的时候通过添加一个对此字段的计数的一个单独的字段。
三. 相关性算分
相关性-relavence
相关性算分,描述一个文档与查询语句的相关度,在查询结果中以_score进行表示
打分的本质是排序,在es5之前,默认的算分算法是TF-IDF,现在的算法叫BM25
搜索步骤:
- 先将一个搜索语句进行词法分析, 切分成一个一个的term
- 找出这些term在文档中的出现的评率,也就是词频
- 根据TF-IDF算法对这些词频与文档进行算分
3.1 TF-词频
词频-term frequency:检索词在一篇文档中的出现的频率,检索词出现的此处除以文档总字数。
度量一个搜索结果与文档的匹配相关性的简单算法:简单地将每个文档中的每一个词频进行相加
- TF(term1)+TF(term2)+TF(term3)
STOP WORD:有一些助词的词频会非常高,但是在搜索语句中的完全没有意义, 例如 的 了,这些不应该考虑他的词频
3.2 IDF-逆文档频率
正如这个名字一样, 逆文档频率就是和词在文档中出现的评率的逆向解析值。就是一个词在所有文档中出现的频率,出现的频率越高,这个IDF的值就会越小。
DF-检索词在所有的文档中出现的频率
IDF = log(文档总数/出现此term的所有的文档数)
term | 出现的文档数 | 总文档数 | IDF |
---|---|---|---|
区块链 | 200万 | 10亿 | log(500)=8.9 |
的 | 10亿 | 10亿 | log(1)=0 |
使用 | 5亿 | 10亿 | log(2) = 1 |
TF-IDF本质就是词频和逆文档率的加权求和过程
DF(TERM1)*IDF(TERM1) + DF(TERM2)*IDF(TERM2) + DF(TERM3)*IDF(TERM3)