https://www.bilibili.com/video/BV1B24y1w7ra/?p=77
这两天看完了这里的最后几个关于suggest的学习视频,
视频中老师提了一个问题:这么几个文档
baoqiang4
baoqiang4 baoqiang3
baoqiang4 baoqiang3 baoqiang2
baoqiang4 baoqiang3 baoqiang2 baoqiang
这么一个查询,因为是popular模式,按理来说,每个词都会有推荐结果的。
但实际上只有前2个有结果,后面两个却没有结果???
这两天看完了这里的最后几个关于suggest的学习视频,
视频中老师提了一个问题:这么几个文档
baoqiang4
baoqiang4 baoqiang3
baoqiang4 baoqiang3 baoqiang2
baoqiang4 baoqiang3 baoqiang2 baoqiang
这么一个查询,因为是popular模式,按理来说,每个词都会有推荐结果的。
但实际上只有前2个有结果,后面两个却没有结果???
7 个回复
Charele - Cisco4321
赞同来自:
就跟那个ES认证一样,其本质上都是入门级别的。
如果以前没接触过suggest,可以看看这个学习视频。
要靠这个要去理解suggest,是不可能的。
这两天一直在琢磨,说一下自己的认识:
(如果你想了解,也可以看看有没有错误什么的)
ES里面,suggest可以分为4种大类:
1 Term suggester
这个本质上等于是执行了一个模糊查询,逻辑也简单。
上面的例子就是
2 Phrase Suggester
看官网的例子,用起来好像很麻烦,忽略
3 Completion Suggester
官网说,它比较耗内存,是因为它的FST表是放内存的。
它能快速查询,为什么快呢,仅仅是因为放内存吗?
那我把普通FST表也强制放内存,不是也快吗?
为什么还要另搞一个completion字段出来呢。
4 Context Suggester
变种,理解了类型3后才能理解
Charele - Cisco4321
赞同来自:
然后为这这个字段插入数据,
后面的suggest查询就围绕此字段进行
Charele - Cisco4321
赞同来自:
在分片数据目录会见到这么些东西,
黄色是completion字段产生的数据文件。
其中红色两个,是completion字段专有的。
除了写普通的FST tip,它会写另外一个FST lkp。
Charele - Cisco4321
赞同来自:
1 如果我执行的是普通termQuery(aaa),
要做的事就是在普通FST中找有没有aaa
2 如果执行的是普通fuzzyQuery(aaa),
1> 根据词aaa,生成fuzzy自动机
2> 结合自动机和FST,执行自动机查询
普通fuzzy查询中这两点,无论哪一点,都是晦涩难懂的。
我相信你是理解不了的:-)
3 回到 Completion Suggester查询
Completion Suggester中可以执行3种子查询类型:
纯prefix, fuzzy, regex(目的都是做前缀推荐)
拿fuzzy子类型来举例:
个人理解,可分为三步:
1> 根据要推荐的词生成对应的自动机
2> 根据自动机在特殊FST里找到关联的key
你的文档已确定,所以有哪些key是可以确定的
比如要推荐"aaa",你会找到 (aaa1, aaa2, a1a),
(比如索引里没有以aaa9开头的文档,所以就不会有aaa9这个key)
用普通FST,也能取到这些key。但是比较费劲。
因为普通FST里的(k, v)对里存的不是词, (源词是存在于词字典tim里面)
特殊FST(k, v) 里直接存的就是词,直接就能拿到
3> 拿到了key(aaa1, aaa2, a1a),
就知道了以这些开头的文档合我的要求,
好像我以这些key分别作普通前缀查询去查一下源文档就可以了。
但实际中,不需要。
只是找一下特殊FST就可以了。因为它里面包括了所有东西(文档号,打分,,,)。
这正是它速度快的原因(另外,这个特殊FST强制放内存里的)
Charele - Cisco4321
赞同来自:
ES层面的代码简单到可以忽略。看下Lucene本质,
1 产生suggest查询所需的自动机,就是上面所说的第一步
说实在的,这块代码细节我没看懂:-(
不过这对于理解suggest不影响,要的只是自动机的判断规则。
2 第2步,找出所有的key (代码中叫做"prefixPath",用Path类来表示)。
其中的红色的FST是那个特殊FST
这一步逻辑相对于第3步来说,比较简单。
前提是要对FST/自动机有一定了解
3 最后就是上面说的第3步,执行实际的推荐查询。
先建一个searcher,把上面得到的key一个一个加进来,然后执行search()。
此方法相对复杂,跟特殊FST的结构相关,下面说说这个FST的结构,,,
Charele - Cisco4321
赞同来自:
当我输入3个文档 "aaa", "aaabbb", "aabbb",
(为了简化,不涉及要分词的情况,比如"aaa bbb")
相比普通FST,这种FST相当的简单明了。
我们晓得,FST也可以看成一个map, 用k可以取出对应的v。
看下第二个文档,词是"aaabbb",
第2行的k,存的就是原始值,(后面的“0 0”跟分词有关,忽略)
v有点复杂,
里面也有原始值"aaabbb",后面黄色的"1f"是分隔符标记,
后面的“1”是文档号
后面的一个数字,就是在输入文档时指定的权重weight(缺省0)。这里用(int Max - weight)。
权重用来对文档进行打分。
我没输入weight,它就是int Max
Charele - Cisco4321
赞同来自:
看下这个"Path"类,