从本篇文章开始介绍Lucene查询阶段的内容,由于Lucene提供了几十种不同方式的查询,但其核心的查询逻辑是一致的,该系列的文章通过Query的其中的一个子类BooleanQuery,同时也是作者在实际业务中最常使用的,来介绍Lucene的查询原理。
查询方式
下文中先介绍几种常用的查询方式的简单应用:
- TermQuery
- BooleanQuery
- WildcardQuery
- PrefixQuery
- FuzzyQuery
- RegexpQuery
- PhraseQuery
- TermRangeQuery
- PointRangeQuery
TermQuery
图1:
图1中的TermQuery描述的是,我们想要找出包含**域名(FieldName)为“content”,域值(FieldValue)中包含“a”的域(Field) **的文档。
BooleanQuery
图2:
BooleanQuery为组合查询,图2中给出了最简单的多个TermQuery的组合(允许其他查询方式的组合),上图中描述的是,我们期望的文档必须至少(根据BooleanClause.Occur.SHOULD)满足两个TermQuery中的一个,如果都满足,那么打分更高。
WildcardQuery
该查询方式为通配符查询,支持两种通配符:
1 | // 星号通配符 * |
星号通配符描述的是匹配零个或多个字符,问号通配符描述的是匹配一个字符,转义符号用来对星号跟问号进行转移,表示这两个作为字符使用,而不是通配符。
图3:
问号通配符的查询:
图4:
图4中的查询会匹配文档3,文档1。
星号通配符的查询:
图5:
图4中的查询会匹配文档0、文档1、文档2、文档3。
转义符号的使用:
图6:
图4中的查询会匹配文档3。
PrefixQuery
该查询方式为前缀查询:
图7:
图7中的PrefixQuery描述的是,我们想要找出包含域名为“content”,域值的前缀值为"go"的域的文档。
以图3为例子,图7的查询会匹配文档0、文档1。
FuzzyQuery
该查询方式为模糊查询,使用编辑距离来实现模糊匹配,下面的查询都是以图3作为例子:
图8:
图8中的各个参数介绍如下:
- maxEdits:编辑距离的最大编辑值
- prefixLength:模糊匹配到的term的至少跟图8中的域值"god"有两个相同的前缀值,即term的前缀要以"go"开头
- maxExpansions:在maxEidts跟prefixLength条件下,可能匹配到很多个term,但是只允许处理最多20个term
- transpositions:该值在本篇文档中不做介绍,需要了解确定型有穷自动机的知识
图8中的查询会匹配文档0、文档1。
图9:
图9中的方法最终会调用图8的构造方法,即maxExpansions跟transpositions的值会使用默认值:
- maxExpansions:默认值为50
- transpositions:默认值为true
图9中的查询会匹配文档0、文档1。
图10:
图10中的方法最终会调用图8的构造方法,即prefixLength、maxExpansions跟transpositions的值会使用默认值:
- prefixLength:默认值为0
- maxExpansions:默认值为50
- transpositions:默认值为true
图10中的查询会匹配文档0、文档1、文档2、文档3。
图11:
图11中的方法最终会调用图8的构造方法,即maxEdits、maxEprefixLength、maxExpansions跟transpositions的值会使用默认值:
- maxEdits:默认值为2
- prefixLength:默认值为0
- maxExpansions:默认值为50
- transpositions:默认值为true
图10中的查询会匹配文档0、文档1、文档2、文档3。
RegexpQuery
该查询方式为正则表达式查询,使用正则表达式来匹配域的域值:
图12:
图12中的RegexpQuery描述的是,我们想要找出包含**域名(FieldName)为“content”,域值(FieldValue)中包含以"g"开头,以"d"结尾,中间包含零个或多个"o"的域(Field)**的文档。
图12中的查询会匹配文档0、文档1、文档2。
PhraseQuery
图13:
该查询方式为短语查询:
图14:
图14中,我们定义了两个Term,域值分别为"quick"、“fox”,期望获得的这样文档:文档中必须包含这两个term,同时两个term之间的相对位置为2 (3 - 1),并且允许编辑距离最大为1,编辑距离用来调整两个term的相对位置(必须满足)。
故根据图13的例子,图14中的查询会匹配文档0、文档1、文档2。
图15:
图15中,我们另编辑距离为0,那么改查询只会匹配文档0、文档1。
图16:
图16中,我们另编辑距离为4,此时查询会匹配文档0、文档1、文档2、文档3。
这里简单说下短语查询的匹配逻辑:
- 步骤一:找出同时包含"quick"跟"fox"的文档
- 步骤二:计算"quick"跟"fox"之间的相对位置能否在经过编辑距离调整后达到查询的条件
TermRangeQuery
图17:
该查询方式为范围查询:
图18:
图18中的查询会匹配文档1、文档2、文档3。
在后面的文章中会详细介绍TermRangeQuery,对这个查询方法感兴趣的同学可以先看Automaton,它通过确定型有穷自动机的机制来找到查询条件范围内的所有term。
PointRangeQuery
图19:
该查询方式为域值是数值类型的范围查询(多维度查询):
图20:
PointRangeQuery用来实现多维度查询,在图19中,文档0中域名为"coordinate",域值为"2, 8"的IntPoint域,可以把该域的域值看做是直角坐标系中一个x轴值为2,y轴值为8的一个坐标点。
故文档1中域名为"coordinate"的域,它的域值的个数描述的是维度的维数值。
在图20中,lowValue描述的是x轴的值在[1, 5]的区间,upValue描述的y轴的值在[4, 7]的区间,我们期望找出由lowValue和upValue组成的一个矩形内的点对应的文档。
图21:
图21中红框描述的是lowValue跟upValue组成的矩形。
故图20中的查询会匹配文档1。
在后面的文章中会详细介绍PointRangeQuery的查询过程,对这个查询方法感兴趣的同学可以先看Bkd-Tree以及索引文件之dim&&dii,这两篇文章介绍了在索引阶段如何存储数值类型的索引信息。
结语
无
点击下载附件