查询DSL(Domain Specific Language)
Domain Specific Language (DSL) 是一种为解决特定领域问题而设计的计算机语言。与通用编程语言(如Java、Python或C++)不同,DSL专注于特定领域的问题和解决方案,提供了更为简洁和高效的方式来表达和处理这些问题。
Elasticsearch DSL设计用来处理各种复杂的搜索场景,支持从简单的文本查询到复杂的聚合查询,还包括过滤、排序和数据分析等功能。Elasticsearch DSL可以分为两大部分:查询DSL和聚合DSL。
查询DSL
- 全文查询(Full Text Queries):如match、multi_match和 query_string,用于执行全文搜索。
- 术语级查询(Term Level Queries):如term、terms和range,用于基于精确值进行过滤。
- 复合查询(Compound Queries):如bool和dis_max,允许将多个查询组合起来,使用逻辑操作符(如AND、OR和NOT)。
聚合DSL
- 度量聚合(Metric Aggregations):如avg、min、max、sum和stats,用于计算数值的统计信息。
- 桶聚合(Bucket Aggregations):如terms、date_histogram和range,用于对文档进行分组。
- 管道聚合(Pipeline Aggregations):对其他聚合的结果进行进一步的处理。
Apache Lucene默认评分公式
在了解那些查询之前,我们将先了解Lucene评分公式的工作原理。评分是Apache Lucene查询处理过程的一个重要环节。评分是指针对给定查询计算某个文档的score属性的过程。它是一个刻画文档与查询匹配程度的参数。下面将讲解Lucene的默认评分机制:TF/IDF(词频/逆文档频率)算法以及它是如何影响文档查询结果的。
注:了解评分公式的工作原理对构造复杂查询以及分析查询中因子的重要性都是很有价值的。同时,掌握Lucene评分机制的基础知识有助于我们更好地优化查询来获取符合我们使用场景的结果。
文档匹配
一个文档被Lucene返回,意味着该文档与用户提交的查询是匹配的。在这种情况下,每个被返回文档会有一个得分,得分越高,文档更相关。文档得分取决于匹配的文档、查询、公式和索引内容等因素。因此,同一文档在不同查询中的得分不具备可比性。主要影响得分的因子有如下这些:
文档权重(document boost):索引期赋予某个文档的权重值。
字段权重(field boost):查询期赋予某个字段的权重值。
协调因子(coord):基于文档中词项个数的协调因子,一个文档命中了查询中的词项越多,得分越高。
逆文档频率(inverse document frequency):一个基于词项的因 子,用来告诉评分公式该词项有多么罕见。逆文档频率越高,词项就越罕见。评分公式利用该因子,为包含罕见词项的文档加权。
长度范数(Length norm):每字段的基于词项个数的归一化因子(在索引期被计算并存储在索引中)。一个字段包含的词项数越多,该因子的权重越低,这意味着Apache Lucene评分公式更“喜欢”包含更少词项的字段。
词频(Term frequency):一个基于词项的因子,用来表示一个词项在某个文档中出现了多少次。词频越高,文档得分越高。
查询范数(Query norm):一个基于查询的归一化因子,它等于查询中词项的权重平方和。查询范数使不同查询的得分能互相比较,尽管这种比较通常是困难和不可行的。
TF/IDF评分公式
了解打分的工作原理非常重要,这有助于简化相关度调优过程。Lucene存在若干打分公式,在这里主要介绍经典的TF/IDF打分公式。
上面的公式融合了布尔检索模型和向量空间检索模型。
布尔检索模型
布尔检索模型是信息检索系统中的一种基本模型,它使用布尔逻辑(如AND、OR和NOT运算符)来处理查询和文档之间的关系。这个模型允许用户通过组合关键词和布尔运算符来构建复杂的查询,从而精确地控制搜索结果应该满足的条件。布尔检索模型的核心特点是简单直接,易于理解和实现,它在早期的文档检索系统中得到了广泛应用。
在布尔检索模型中,文档集合被视为由独立文档组成,每个文档由一组词(或术语)来描述。查询也是由一组词构成,这些词通过布尔运算符(AND、OR、NOT)连接起来。检索系统根据这些布尔表达式来判断哪些文档与查询匹配。
- AND运算符:要求文档必须包含所有用AND连接的词。例如,查询“Python AND Django”将返回包含“Python”和“Django”这两个词的文档。
- OR运算符:要求文档至少包含用OR连接的词之一。例如,查询“Python OR Django”将返回包含“Python”或“Django”(或两者都包含)的文档。
- NOT运算符:排除包含特定词的文档。例如,查询“Python NOT Django”将返回包含“Python”但不包含“Django”的文档
布尔检索模型的优点
- 简单直观:布尔查询易于理解和使用,用户可以通过简单的逻辑组合来构建复杂的查询。
- 精确控制:用户可以精确地指定文档必须满足的条件,有助于缩小搜索范围。
- 适用性广:布尔检索模型不依赖于特定的语言或领域,适用于各种文档和数据集。
布尔检索模型的缺点
- 结果过多或过少:复杂的布尔查询可能导致零结果或太多不相关的结果,特别是对于非专业用户来说,很难平衡查询的精确性和召回率。
- 无法排序:布尔模型通常不提供关于文档与查询匹配程度的排序,因为它只关心文档是否匹配给定的布尔表达式。
- 不支持部分匹配:布尔模型不考虑词的重要性或文档中词的频率,也不支持查询和文档之间的部分匹配。
向量空间检索模型
向量空间模型(Vector Space Model, VSM)是信息检索领域中一种广泛使用的模型,它将文档和查询表示为向量,从而在多维空间中对它们进行表示和比较。这种模型的核心思想是通过空间中的向量相似度来衡量文档和查询之间的相关性,常用的相似度计算方法包括余弦相似度(Cosine Similarity)。
在向量空间模型中,每个维度代表一个唯一的术语(通常是文档集合中的单词),因此一个文档或查询可以被表示为一个术语向量。文档或查询中的每个术语对应于向量中的一个权重,这个权重反映了该术语在文档或查询中的重要性。权重可以通过各种方法计算,最常见的是TF-IDF(Term Frequency-Inverse Document Frequency)。
关键概念
- 术语频率(TF):一个术语在文档中出现的频率,表示该术语在文档中的重要性。
- 逆文档频率(IDF):用于衡量一个术语的普遍重要性。它是文档集合的总文档数目除以包含该术语的文档数目的对数。
- TF-IDF权重:一个术语的TF乘以其IDF,用于减少常见术语的影响同时增加罕见术语的权重。
优点
- 灵活性:向量空间模型可以容纳不同的权重计算方法,如TF-IDF、BM25等。
- 直观:通过向量表示,文档和查询之间的相似度可以直观地通过角度来理解,余弦相似度是一种常用的度量方法。
- 排名能力:与布尔模型相比,向量空间模型可以根据相似度对搜索结果进行排名,提供更丰富的信息检索体验。
缺点
- 维度灾难:在包含大量唯一术语的文档集合中,向量的维度可能非常高,导致计算和存储开销大。
- 无语义理解:向量空间模型基于词汇的字面匹配,缺乏对词义的理解,可能无法有效处理同义词和多义词问题。
现在回到Lucene的打分公式,其是一个关于查询q和文档d的函数。有两个因子并不直接依赖查询词项,它们是coord和queryNorm,这两个因子与查询词项的一个求和公式相乘便得到了文档得分。求和公式中每个加数由以下因子连乘所得:词频,逆文档频率,词项权重,范数。
根据上述公式,我们可以推导出一些规则:
- ·越罕见的词项被匹配上,文档得分越高。Lucene认为包含独特单 词的文档比包含常见单词的文档更重要。
- 文档字段越短(包含更少的词项),文档得分越高。通常,Lucene更加重视较短的文档,因为这些短文档更有可能和我们查询的主题高度吻合。
- 权重越高(不论是索引期或是查询期赋予的权重值),文档得分越高。因为更高的权重意味着特定数据(文档、词项、短语等)具有更高的重要性。
Elasticsearch中的评分
Elasticsearch使用了Lucene的评分功能,但我们可以挑选可用的similarity类实现,或者自定义similarity类,来替换默认的评分算法。也可以使用各种不同的查询类型,以精确控制文档评分的计算。例如使用function_score查询时,可以通过使用脚本(scripting)来改变文档得分。亦或通过在返回文档集之上执行另外一个查询,重新计算top-N文档的得分。