是时候用 ES 拯救发际线啦

关于Lucene的正则查询

Lucene | 作者 Charele | 发布于2024年05月17日 | 阅读数:2727

regexpQuery,一个稍微有点复杂的主题,也许没人愿意花时间去了解它。
有人会说影响性能,不过这不是关注点,
理解它,才是目的。
1111.PNG

这是我理解中的自动机查询(每个人看法可能不同)的执行流程,
要说的就是第1个步,如何生成正则自动机。
(除了第1步,共它步骤对于所有自动机类型查询来说都是一样的)
 
第1步,因查询类型不同而不同,除了正则和模糊这两个,其它都很简单。
第6步,"next()方法“,在IntersectTermsEnum类,理解起来,不是一般的困难!
 
 图里面的“自动机规则”,并不是一个具体Java类,
而是用来判断一个文档中的词合不合要求的东西,

 
 另外的第2,3,4,5步,这个博客里都有很详细的描述:
I https://amazingkoala.com.cn/un ... .html
II https://amazingkoala.com.cn/un ... .html
III https://amazingkoala.com.cn/un ... .html
 
 
这个文章还行:https://blog.csdn.net/xgx82261 ... 6683/
不过如果你看过上面的博客,这也就没什么价值了, 
基本上就是copy了博客里的内容
已邀请:

Charele - Cisco4321

赞同来自:

1111.PNG

正则表达式千变万化,我也不懂正则这个东东。
拿宫 网的这个简单例子来说明。
 
这里框出来,标上1,2,是和下面要说的有关系

Charele - Cisco4321

赞同来自:

4444.png

生成正则自动机,本质上就是这两大步:
 
 
1“解析“这一步,没什么好说的,一个一个字母的分析,生成对应的自动机树。
就是看到什么字符做什么动作(生成某种子自动机,加到树上),
如果你精通正则表达式,理解起来就很容易。 
  我们知道,Java里有一个类java.util.regex.Pattern,跟正则相关。
但Lucene没有用到这个,而是自己去分析
 
上面那个查询,会生成这样一颗树:
(下面6行,每一行都代表一个命令,执行命令的结果就是生成一个自动机)
 
REGEXP_CONCATENATION                                  根树
-----REGEXP_CONCATENATION                           子树1
---------REGEXP_CHAR char=W
---------REGEXP_CHAR_RANGE from=0 to=9       
-----REGEXP_REPEAT_MIN min=1                         子树2
---------REGEXP_ANYCHAR
 
对照楼上对"W[0-9].+"的解释,一看就能明白这树是什么意思 
其中的子树1和子树2,就是上楼黄色框里的。
(也可以看成左子树和右子树)
 为什么分为子树1和2?更复杂的正则,会不会有子树3,4,,,?
 
这是因为程序里就这么写的,无论正则是啥样,它都分为两个。
(这是一个嵌套,儿子也可以有自己的儿子)
2222.PNG

如果你的正则很简单,比如"abc",也分不出子树了,
这两个对像就是null。
 
 2 处理的过程,就是按树结构,生成最终的,能表达正则的自动机。
针对不同的正则树不同,处理过程也会不同。有创建,合并,去重,,,等等。
 比如这里,子树1底下有两个条目,
会先拼接(CONCATENATION) 这两个条目,生成子树1。然后生成子树2,
最后拼接子1和子2,生成结果自动机

Charele - Cisco4321

赞同来自:

自动机1.PNG

先搞一个博客截图,这是范围查询的自动机样子。
和FST里的隐式节点不同,这里的节点是真实存在的。
 
PS:节点编号,并不是固定不变的,它是可变换的。
只要执行逻辑不变就行,比如入口0必须还是这一块自动机的入口 
 
 
回到本例,从树上可以看出,生成过程分3步是:子树1 ---》 子树2 ---》 根树自动机, 
树上有两个“拼接”过程,实际中合在一起了,所以会执行下面:
一 生成一个“只接受'W'的自动机
二 生成一个只接受['0', '9']的自动机
三 生成一个"接受Any字符(最少一个)“的自动机
四 把上面3个自动机拼接起成一个自动机
五 "最小化"(最小化就是去掉里面多余无用的节点)上面的自动机,返回
 
一 生成自动机,它只接受字母'W'
3333.png

二 同上,只是范围换成['0', '9']

Charele - Cisco4321

赞同来自:

三 生成一个"接受Any(最少一个)“的自动机
这一步有点复杂,可细分为下面几步
1 生成一个"接受Any字符"的自动机A
2 实现“最少n个自动机A”(本例,就是n个Any字符),这一步会生成n+1个自动机
3 拼接上面的n+1个自动机,生成B
4 最小化B, 生成C, 返回
 

1111.PNG
就本例来说,最后的结果是很简单的。这是基于1处的自动机是简单的,
如果它是很复杂的,且是“最小100个”呢?其结果就复杂了
 
看下2处的repeat(a, min)方法,它是如何实现的

要回复问题请先登录注册