背景
上一篇文章我们提到了 搜索引擎:Lexical Parser 成分解析
ES里没有这种模块,他是怎么实现这个类似的功能的呢
分析
假设我们的原始数据是
// doc1
{
"city": "南京",
"type": "租房",
"desc": "南京租房挺便宜"
}
// doc2
{
"city": "南京",
"type": "二手房"
"desc": "南京二手房老贵了"
}
假设我们对city字段和type字段建索引,得到的倒排索引应该类似这样:
city_南京:doc1 doc2
type_租房:doc1
type_二手房: doc2
先看使用lexical parser的搜索流程
query = 南京租房
经过lexical parser分析
得到 [city=南京] [type=租房]
我们取两个倒排索引的交集,也就是”与“的关系:city=南京
and type=租房
于是我们取上面两个拉链的交集,就是doc1。
于是我们知道doc1里 包含city=南京
type=租房
,检索成功出来doc1
再看ES的搜索流程
ES会对使用某种分词器进行分词:
query = 南京租房
分词后得到
[南京] [租房]
默认情况下会去搜索所有拉链
找到拉链:
city_南京:doc1 doc2
type_租房:doc1
一般,只要有一个匹配就能召回 然后通过 tf/idf等算法对所有召回的结果算法进行排序,提高准确率
顺便聊聊 tf/idf
假设公式真就简化成 tf * idf,那么这两个文档分别得分是多少?
tf: term frequency,词在文档中出现了多少次
比如 文档1中,文档经过分词后,是: [南京 租房 南京 租房 挺 便宜],分母是6,
南京在doc1中出现了2次, tf1(南京) = 2/6
同理tf1(租房)=2/6
tf2(南京)=2/6
idf:inverse doc frequency,多少个文档里包含这个词
idf(南京) = 2 / 2 = 1
idf(租房) = 2 / 1 = 2
计算两个文档的得分
tf1 = tf1(南京) * idf(南京) + tf1(租房) * idf(租房) = 2/6 * 1 + 2/6 * 2= 1
tf2 = tf2(南京) * idf(南京) = 2/6 * 1 = 1
明显文档1得分高,文档1胜出!符合预期!
附:
es怎么计算相关性的:https://www.elastic.co/guide/cn/elasticsearch/guide/cn/relevance-intro.html