ElasticSearch搜索代码解析

  • MDAGNode结点结构图1:

在这里插入图片描述

在这里插入图片描述

图2-前缀树-字典

不同结点有不同的地址值,不同边也有相对应的地址值,但是所有的接收状态结点即最终结点都指向同一地址。

一、搜索过程

以下默认编辑距离是2,以查询fr为例;

  1. 创建包含字典的数据结构

    **ArrayList<String> myArrayList = **new ArrayList(Arrays.asList(new String[]{"ab", "cdf", "def","fri"}));
    **MDAG myMDAG =** new MDAG(myArrayList);
    到此,字典就建成一棵前缀树了,如图2所示。

  2. 三种方式查询方式:

    1. 通过表格确定字典中距“树”的编辑距离2以内的所有字符串(理想的用例:编辑距离<= 2)

**LinkedList<String> ldNeighborsLinkedList = **LevenshteinAutomaton.tableFuzzySearch(2, "fr", myMDAG); //"fr", "fri"

  1. 通过动态编程确定字典中距“树”的编辑距离2以内的所有字符串(理想的用例:内存容量低,编辑距离> = 2)

**LinkedList<String> ldNeighborsLinkedList =** LevenshteinAutomaton.fuzzySearchNonAutomaton(2, "fr", myArrayList); //"fr", "fri"
c.** 通过自动机遍历字典中与“树”的编辑距离为2的所有字符串**
**LinkedList<String> ldNeighborsLinkedList = **LevenshteinAutomaton.iterativeFuzzySearch(2, "fr", myMDAG); //"fr", "fri"

方法内部的大体流程为:

  1. 依次遍历整体树,首先可以先遍历第一层得到“a,c,d,f”压栈,然后可以找到“fri”这一支;
  2. 之后,先遍历f 这一结点,然后通过State中的相关词函数-getRelevantSubwordCharacteristicVector(),找到待检查词“fri”的相关词,并返回AugBitSet格式的数据,数据里存储的是与“fri”相关词向量和相关词与检索向量之间的碰撞位置;(碰撞位置不太了解)
  3. 再则,通过State里的transition(),读取相关词向量、编辑距离等信息,之后,**transitionInternal()根据最大编辑距离、相关子字符串、碰撞位置信息等来为positon类内部设置的枚举类型赋值,从而procureTransition()**判断出可能的所有状态(相关词不定,正在处理的字符为f,可能的状态为插入、替换、删除),并把结果以数组的形式返回。之后,**execute()**根据目前的状态切换到下一个位置(改变I和E的值),接着处理下一个字符r,依次类推,直到正在处理的结点是接收状态结点,就结束,因为只要最后一个可以变换成目标。
  4. 最后,到其它支,发现“a,c,d”都不能在2个编辑距离之内转换成fri,因此进行剪枝策略。

二、再来了解几个重要类和函数:
1. State:Position数组是成员变量,此数组内部包含全部可能的转换情况,例如fri和f最比较可能是插入、删除;

函数:

2. getRelevantSubwordCharacteristicVector:根据相关词的公式,获取到与待检索词的相关词的长度

(相关词:在该长度内,在编辑距离的限制下,可准确的判断出该向量是否有可能转化成待检索词)

3. transition:调用position的内部方法,进行状态的转换
4. AugBitSet:Bitset的继承类,用来储存相关词向量和检索向量之间的碰撞位置,如f和frien则会产生(1,0,0,0,0)
5. Position:

成员:

I(目前正在处理的字符的位置,例如stand中的s为0、t为1)
E(目前已经进行了多少次编辑)
T(是否为可接受状态)
注:可近似对比为NFA图,I为横坐标、E为纵坐标

状态:

MATCH:匹配,eg: s,正在处理的字符串为s
INSERTION:插入,eg: s,正在处理的字符串为s,结果为ss
PRETRANSPOSITION
TRANSPOSITION
SUBSTITUTION:eg: 替换,s,正在处理的字符串为w,结果为w
DELETION:删除,eg: ss,结果为s
FAILURE:失败状态,后续的枝条将会被剪掉,成为剪枝

方法:

execute:根据目前的状态切换到下一个位置(改变I和E的值)
procureTransition:根据内部设置的枚举类型,判断出可能的所有状态(st,正在处理的字符为t,可能的状态为插入、替换、删除),结果以数组的形式返回
transitionInternal:根据最大编辑距离、相关子字符串、碰撞位置信息等来为positon类内部设置的枚举类型赋值,从而使procureTransition方法可以调用
编辑距离相关函数

  1. 确定两个单词之间的编辑距离

int editDistance **= **LevenshteinAutomaton.computeEditDistance("fri", "frien"); //1

  1. 确定两个字符串是否在彼此的给定编辑距离内

**boolean areLDNeighbors =** LevenshteinAutomaton.areWithinEditDistanceNonAutomaton(2, "fri", "frien"); //true

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值