Lucene 查询原理解析

本文主要介绍 Lucene 的查询过程和基本原理,从原理和源码级别对查询过程做了描述和分析,可以让你对 Lucene 底层的查询逻辑和过程有个整体的了解。基于此目的,部分细节可暂不做深入探究(如部分索引文件的数据结构等),不影响整体的认知。

说明:本文基于 Lucene 版本 7.2.1,对应 Elasticsearch 版本 6.2.3(公司在用的ES版本),不同的版本可能有些许差异。

一、查询类型

在了解 Lucene 的查询流程之前,我们先认识一下 Lucene 中的几个重要的查询类型。

Lucene 7.2.1 中有以下 Query (具体介绍见org.apache.lucene.search.Query)

lucene.apache.org/core/7_2_1/…

下面列出一些常见的 query 及对其基本用途做个简单描述:

  • TermQuery

    A Query that matches documents containing a term. This may be combined with other terms with a BooleanQuery.

    指定某个字段(field)包含某个值。等同于关系型数据库中的 where col = v

  • BooleanQuery

    A Query that matches documents matching boolean combinations of other queries, e.g. TermQuerys, PhraseQuerys or other BooleanQuerys.

    一个可包含多个 query 的组合,如 "TermQuery" + "PhraseQuery" 或者其他 bool 类型的 Query。

  • WildcardQuery

    Implements the wildcard search query. Supported wildcards are *, which matches any character sequence (including the empty one), and ?, which matches any single character. '' is the escape character.

    通配符查询,可以使用*?这样的通配符,表示匹配任意个字符。注意:wildcard 查询很慢,为了避免极慢的查询(extremely slow),最好不要使用以“*”开头的 wildcard 查询。

    • Elasticsearch实践)wildcard 的使用在生产环境上应该特别注意,当数据量达到一定的规模,对一个 text 字段做 wildcard 查询时,及其损耗 CPU 性能,容易引发 CPU 尖刺,给 ES 的集群稳定性代理一定的影响,严重的话可能引起整个集群的崩塌,慎重!故应该尽量避免这种场景或使用其他替代方案。

    • Case: 订单号、手机号或者某些较短文本的匹配

      可以使用“ngram分词” + TermsQuery 查询的方式满足查询场景,且在数据量较大时,极大地提升查询性能(空间换时间)。

  • PhraseQuery

    A Query that matches documents containing a particular sequence of terms. A PhraseQuery is built by QueryParser for input like "new york".

    顾名思义,短语匹配:一个文档字段中的值包含一整个短语(有可能是多个 term),如“new york”这个短语,会构建“new york”的短语匹配查询,只有按顺序出现(new在前,york 在后),才可以命中该文档。

    • 当然,可以调整“slop”的值为 1,意为可以移动一个短语的次数,即,可以将“york往前移动一个位置”,那么这个查询条件将会同时匹配“new york” 和 “york new”命中的文档
  • PrefixQuery

    A Query that matches documents containing terms with a specified prefix. A PrefixQuery is built by QueryParser for input like app*.

    前缀匹配查询,简单理解可以认为是 PhraseQuery 的更细化的场景。

  • MultiPhraseQuery

    • 可以理解成 PhraseQuery(短语匹配查询)的一种更泛化或更为通用的版本。如搜索“Microsoft app*”,使用 MultiPhraseQuery 构建,会先生成“Microsoft”这个TermQuery,再生成满足“app”这个前缀的所有 Term 查询,最后将他们合并在一起做查询。
  • FuzzyQuery

    Implements the fuzzy search query. The similarity measurement is based on the Damerau-Levenshtein (optimal string alignment) algorithm, though you can explicitly choose classic Levenshtein by passing false to the transpositions parameter.

    • 使用编辑距离(莱文斯坦距离)算法计算相似度的查询

      编辑距离,又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。

    At most, this query will match terms up to 2 edits. Higher distances (especially with transpositions enabled), are generally not useful and will match a significant amount of the term dictionary. If you really want this, consider using an n-gram indexing technique (such as the SpellChecker in the suggest module) instead.

    • 官方建议,编辑值不要大于 2,生产环境上可以使用 n-gram 分词器对指定字段分词,否则会在查询过程中命中大量的文档,从而对最终的查询性能产生较大的影响。
  • RegexpQuery

    • 正则模糊匹配,这个查询在生产环境并不建议使用,应尽量避免。原因同“wildcardQuery”,此处不做赘述
  • TermRangeQuery

    A Query that matches documents within an range of terms.

    指定term短语范围的查询,一般字符串范围按照 ascII 码排序。

  • PointRangeQuery

    range queries against single or multidimensional points such as IntPoint.

    坐标点的范围查询,常见于经纬度范围查询。

  • ConstantScoreQuery

    A query that wraps another query and simply returns a constant score equal to 1 for every document that matches the query. It therefore simply strips of all scores and always returns 1.

    包装了其他的查询,评分都为常量值 1

二、查询流程

先上一个 Lucene 查询的流程图:

  • Lucene 查询原理解析_第1张图片

你可能感兴趣的:(lucene,elasticsearch,搜索引擎)