当前位置:   article > 正文

Elasticsearch Query DSL之全文检索(Full text queries)

Elasticsearch Query DSL之全文检索(Full text queries)

“_type”:“matchquerydemo”,

“_id”:“1”,

“_score”:0.2876821,

“_source”:{

“context”:“Brown rabbits are commonly seen.”,

“title”:“Quick brown rabbits”

}

}

]

}

}

best_fields类型内部会转换为(dis_max):

GET /_search

{

“query”: {

“dis_max”: {

“queries”: [

{ “match”: { “subject”: “brown fox” }},

{ “match”: { “message”: “brown fox” }}

],

“tie_breaker”: 0.3

}

}

}

通常best_fields类型使用单个最佳匹配字段的分数,但如果指定了tie_breaker,则其计算结果如下:最佳匹配字段的分数加上 tie_breaker * _score(其他匹配字段分数)。该查询模式支持match query相关的参数,例如analyzer, boost, operator, minimum_should_match, fuzziness, lenient, prefix_length, max_expansions, rewrite, zero_terms_query, cutoff_frequency, auto_generate_synonyms_phrase_query 、fuzzy_transpositions等参数。

best_fields和大多数字段类型都是以字段为中心的——它们为每个字段生成匹配查询。这意味着运算符和minimum_should_match参数将分别应用于每个字段。

4.1.1.2 most_fields

查找匹配任何字段并结合每个字段的_score的文档,Elasticsearch会为每个字段生成一个match查询,然后将它们包含在一个bool查询中。其算法的核心是各个字段的评分相加作为文档的最终得分参与排序。其建议场景是不同字段对同一关键字的存储维度不一样,例如字段一可能包含同义词、词干、变音符等;字段二可能包含原始词根,这种情况下综合各个字段的评分就会显的更加具有相关性。

该查询模式支持match query相关的参数,例如analyzer, boost, operator, minimum_should_match, fuzziness, lenient, prefix_length, max_expansions, rewrite, zero_terms_query, cutoff_frequency, auto_generate_synonyms_phrase_query 、fuzzy_transpositions等参数。

4.1.1.3 phrase、phrase_prefix

这两种类型score的计算采用best_fields方法,但是其查询方式分别为match_phrase、match_phrase_prefix。

4.1.1.4 cross_fields

交叉字段,对于需要匹配多个字段的结构化文档,cross_fields类型特别有用。例如,在查询“Will Smith”的first_name和last_name字段时,在一个字段中可能会有“Will”,而在另一个字段中可能会有“Smith”。这听起来很象most_fields,cross_fields与most_fields的两个明显区别如下:

对于opreator、minimum_should_match的作用域不一样,most_fields是针对字段的,(遍历每个字段,然后遍历查询词根列表,进行逐一匹配),而cross_fields是针对词根的,即遍历词根列表,搜索范围是所有字段。

相关性的考量不相同,cross_fields重在这个交叉匹配,对于一组查询词根,一部分出现在其中一个字段,另外一部分出现在另外一个字段中,其相关性计算评分将更高。

举例说明:例如有如下查询语句:

{

“query”: {

“multi_match” : {

“query”: “Will Smith”,

type”: “cross_fields”,

fields”: [ “first_name”, “last_name” ],

“operator”: “and”

}

}

}

其执行操作时,首先对查询字符串分析得出will、smith两个词根,然后遍历这两个词根,一次对 first_name,last_name 进行匹配,也就是说 opreator、minimum_should_match 这些参数作用2次,而 most_fields 方式,是一个嵌套循环,先遍历字段,然后对每一个词根在该字段上进行匹配,在该示例中,opreator、minimum_should_match 这些参数作用4次。

4.1.2 tie_breaker属性

默认情况下,每个词汇混合查询将使用组中任何字段返回的最佳分数,然后将这些分数相加,以给出最终分数。tie_breaker参数可以改变每项混合查询的默认行为。tie_breaker可选值如下:

  • 0.0 : 默认行为,使用最佳字段的score。

  • 1.0 :所有匹配字段socre的和。

  • 0.0 ~ 1.0 : 使用最佳匹配字段的score + (其他匹配字段score) * tie_breaker。

4.1.3 multi_query支持其他match query参数

其他诸如analyzer, boost, operator, minimum_should_match, fuzziness, lenient, prefix_length, max_expansions, rewrite, zero_terms_query, cutoff_frequency, auto_generate_synonyms_phrase_query 、fuzzy_transpositions等参数,multi_query同样支持。

5、common terms query


定位:排除停用词或高频词对文档的匹配影响。提高文档匹配的精确度,同时不对性能产生影响。

我们来看一个停用词(高频词)对文档过滤帅选带来的影响:

查询字符串中的每个词根都有搜索成本。搜索“the brown fox”需要三个词根查询,分别为“The”、“brown”和“fox”,所有这些查询都是针对索引中的所有文档执行的。

对于“The”的查询可能匹配许多文档,因此对相关性的影响要比其他两个术语小得多。

一种解决这个问题的方法是忽略高频项。通过将“the”视为stopword(停用词),我们可以减少索引大小并减少需要执行的词汇查询的数量。这种方法的问题在于,尽管停止语对相关性的影响很小,但它们仍然很重要。

如果我们去掉stopwords,我们就会失去精确性(比如我们无法区分“快乐”和“不快乐”),我们就会失去回忆(比如像“The The The”或“to be or not to be”这样的文本就不会存在于索引中)。

本文将介绍另外一种方式来解决上述问题:

common terms query 将查询词根分为两组:更重要的(即低频词根)和不那么重要的(即高频词根,以前应该是停止词)。

首先,它搜索与更重要的词根(低频词)匹配的文档。这些术语出现在较少的文档中,对相关性的影响更大,性能更好。

然后,它对不太重要的词根(高频词)执行第二个查询。但是它并不会计算所有匹配(匹配高频词的所有文档)文档的相关得分,而是只计算第一个查询已经匹配的文档的_score。通过这种方式,高频项可以在不付出性能差的代价的情况下改进关联计算(低频词、高频次相互关联)。

如果查询只包含高频术语,那么一个查询将作为AND(连接)查询执行,换句话说,所有的词根都必须满足。尽管每个单独的词根将匹配许多文档,但术语组合将结果集缩小到最相关的部分,当然单个查询也可以作为或以特定的minimum_should_match执行。

词根根据cutoff_frequency被分配给高频或低频组,可以指定为绝对频率(>=1)或相对频率(0.0)。1.0)。

5.1 示例详解

5.1.1 简单使用说明

GET /_search

{

“query”: {

“common”: {

“body”: {

“query”: “this is bonsai cool”,

“cutoff_frequency”: 0.001

}

}

}

}

会对查询词根 this、is、bonsai、cool4个词根分词,词根频率小于0.001的bonsail、cool会被当成低频次,而this、is会被设置为高频词组。由于common term query将词根分成了低频组与高频组,故针对match query的operator、minimum_should_match分别由如下四个参数代替:low_freq_operator、high_freq_operator、minimum_should_match:{low_freq、hign_freq}。

java rest api使用示例如下:

public static void testCommonQuery() {

RestHighLevelClient client = EsClient.getClient();

try {

SearchRequest searchRequest = new SearchRequest();

searchRequest.indices(“esdemo”);

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

sourceBuilder.query(

QueryBuilders.commonTermsQuery(“context”, “this is brown fox”)

.cutoffFrequency(0.001f)

.highFreqOperator(Operator.OR)

.highFreqMinimumShouldMatch(“3”)

.lowFreqOperator(Operator.OR)

.lowFreqMinimumShouldMatch(“2”)

);

searchRequest.source(sourceBuilder);

SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);

System.out.println(result);

} catch (Throwable e) {

e.printStackTrace();

} finally {

EsClient.close(client);

}

}

6、query_string query


查询字符串方式。query_string查询解析器支持对查询字符串按照操作符进行切割,每个部分独立分析,例如:

GET /_search

{

“query”: {

“query_string” : {

“default_field” : “content”,

“query” : “(new york city) OR (big apple)”

}

}

}

query_string的顶层参数如下:

| 参数名 | 描述 |

| — | — |

| query | 查询字符串。 |

| default_field | 默认匹配字段,如果未设置,则为"*",表示所有的字段,也可通过index.query.default_field来统一配置默认字段。 |

| default_operator | 设置默认操作类型,可选值:Operator.OR 和 Operator.AND,默认为Operator.OR。 |

| analyzer | 设置分词器。 |

| quote_analyzer | 用于分析查询字符串中引用的短语的分析器的名称。对于这些部分,它覆盖了使用analyzer参数或search_quote_analyzer设置设置的其他分析器。 |

| allow_leading_wildcard | 是否允许第一个字符为通配符(*或?),默认为允许。 |

| enable_position_increments | 是否允许以在结果查询中启用位置增量。默认值为true。 |

| fuzzy_max_expansions | 控制模糊匹配的词根的扩展个数,在match phrase prefix的max_expansions已详解,默认为50。 |

| fuzziness | 设置为模糊匹配。 |

| fuzzy_prefix_length | 模糊查询设置前缀长度。默认值为0。 |

| fuzzy_transpositions | 是否开启模糊互换(ab -> ba)。默认为true。 |

| phrase_slop | match_phrase查询的slop。 |

| boost | 设置查询的boost值。默认为1.0。 |

| auto_generate_phrase_queries | 是否自动生成短语查询(match_phrase),默认为false。 |

| analyze_wildcard | 默认情况下,查询字符串中的通配符项不会被分析。通过将该值设置为true,还将尽力分析这些值。 |

| max_determinized_states | 设置可以创建自动状态机(正则表达式),默认为 10000。 |

| minimum_should_match | 具体参考match_query的minimum_should_match。 |

| lenient | 是否忽略由于数据类型不匹配引起的异常,默认为false |

| time_zone | 时区应用于与日期相关的任何范围查询。参见JODA时区。 |

| auto_generate_synonyms_phrase_query | 在使用match_phrase_query查询时开启同义词匹配,默认为true. |

| all_fields | 6.4.0版本后已废弃,使用default_field。 |

6.1 多字段支持(multi field)

query_string支持多字段查询,可通过fields属性指定,例如:

GET /_search

{

“query”: {

“query_string” : {

“fields” : [“content”, “name”],

“query” : “this AND that”

}

}

}

其含义类似于:“query”: “(content:this OR name:this) AND (content:that OR name:that)”。

同时query_string(查询字符串)模式同样支持match_query等查询对应的参数,其工作机制一样,示例如下:

GET /_search

{

“query”: {

“query_string” : {

“fields” : [“content”, “name^5”],

// “fields” : [“city.*”],

“query” : “this AND that OR thus”,

“tie_breaker” : 0,

“type”: “best_fields”,

“auto_generate_synonyms_phrase_query” : false (同义词synonym机制)

}

}

}

6.2 支持通配符

查询字符串中支持使用通配符?与*,其中?表示的单个字符,而_表示0个或多个字符。查询字符串使用通配符,可能会消耗更多的内存,查询性能较低下。为了提高通配符效率,如果只是一个_的话,命令就会被重写为存在查询(是否存在文档),例如fields:[“*”]。在关系型数据库中前置通配符(" _ab"),这种查询是不支持索引查询的,在es中同样如此,需要遍历索引中所有词根,可以通过allow_leading_wildcard=false来禁用这种查询。通过将analyze_wildcard设置为true,将分析以_结尾的查询,并从不同的令牌构建布尔查询,方法是确保第一个N-1令牌上的精确匹配,以及最后一个令牌上的前缀匹配。

6.3 支持正则表达式

正则表达式可以嵌入到查询字符串中,方法是将它们包装成斜杠(“/”)。注意allow_leading_wildcard无法控制正则表达式的行为。

6.4 邻近查询(可前可后)

虽然短语查询match_phrase(如“john smith”)要求所有的术语都按照完全相同的顺序进行查询,但是接近查询允许指定的单词进一步分开或以不同的顺序进行查询,并且也提供诸如match_query的slop属性。例如:“fox quick”~5。

6.5 范围查询

可以为日期、数字或字符串字段指定范围查询。包含范围用方括号[min到max]指定,排他范围用花括号{min到max}指定。例如如下:

  • 日期在2012年之内。

date:[2012-01-01 TO 2012-12-31]

  • 大于等1,小于等5

count:[1 TO 5]

  • Tags在 alpha 和omega之间,但不包括alpha和omega

tag:{alpha TO omega}

  • 大于等于10

count:[10 TO *]

  • 日期小于2012年

date:{* TO 2012-01-01}

6.6 搜索字符串权重提升

使用提高运算符可以设置一个词根相比其他词根更加重要(相关性更高)。例如针对查询字符串"quick2 fox",表明quick这个词根的重要性比fox重要2倍。该操作符也可以针对短语或组,一个组用()表示,示例如下:“john smith”^2 (foo bar)^4。

6.7 boolean运算

默认情况下,所有词根都是可选的,只要一个词根匹配即可(Opreator.OR),从上面得知通过修改default_operator可以改变其默认行为。ES还支持对查询字符串进行boolean运算。例如查询字符串“quick brown +fox -news”表示的含义是:

  1. fox词根必须存在。

  2. news词根必须不存在。

  3. quick brown 可选。

也支持常见的布尔运算符AND, OR和NOT(也写为&&,||和!),但要注意,它们不遵守通常的优先规则,因此当多个运算符一起使用时,应该使用括号。例如,前面的查询可以改写为:((quick AND fox) OR (brown AND fox) OR fox) AND NOT news。

6.8 分组(grouping)

多个词根或子句可以用括号组合在一起,形成子查询,例如(quick OR brown) AND fox。

6.9 转义字符

在ES中,如下字符需要使用转义符合\,保留字符是:+ - = && || > < !(){ }[]”^ ~ * ?:\ /。

6.10 空查询

如果查询字符串为空或仅包含空白,则查询将生成空结果集。

6.11 query_string示例

public static void testQueryStringQuery_Query() {

RestHighLevelClient client = EsClient.getClient();

try {

SearchRequest searchRequest = new SearchRequest();

searchRequest.indices(“esdemo”);

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

sourceBuilder.query(

// QueryBuilders.queryStringQuery(“brown -fox”)

// QueryBuilders.queryStringQuery(“brown^8 fox^2”)

QueryBuilders.queryStringQuery(“(quick OR brown) AND fox”)

.allowLeadingWildcard(false)

.field(“context”)

.field(“title”)

// .minimumShouldMatch(“1”)

);

searchRequest.source(sourceBuilder);

SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);

System.out.println(result);

} catch (Throwable e) {

e.printStackTrace();

} finally {

EsClient.close(client);

}

}

测试情况如下:

目前范围查询暂不知如何编写查询字符串,但ES专门通过QueryBuilders.rangeQuery(String name)返回RangeQueryBuilder,邻近查询未能编写Demo。

7、simple_query_string query


简单字符串查询模式。使用SimpleQueryParser解析上下文的查询。与常规的query_string查询不同,simple_query_string查询永远不会抛出异常,并丢弃查询的无效部分。下面是一个例子:

GET /_search

{

“query”: {

“simple_query_string” : {

“query”: ““fried eggs” +(eggplant | potato) -frittata”,

“fields”: [“title^5”, “body”],

“default_operator”: “and”

}

}

}

查询字符串的写法非常符合(query_string)中定义的,例如查询字符串中支持boolean运算等。simple_query_string中的顶级参数都定义在org.elasticsearch.index.query.SimpleQueryStringBuilder中,其含义与query_string中类似,在这里就不重复介绍了。

simple_query_string支持如下写法。

  • +signifies 表示必须包含。

  • | signifies 相当于OR。

  • negates 相当于非

  • " 包装一些标记以表示搜索的短语

    • 例如a*,表示前缀匹配
  • ( and ) 括号可表示优先级

  • ~N after a word 表示模糊匹配举例,类似于match_phrase slop。

  • ~N after a phrase(短语),表示溢出量。

上述这些写法与在query_string机制一样。接下来主要再讲述query_string不同点。

7.1 flags

simple_query_string支持多个标记来指定应该启用哪些解析特性。它被指定为一个|分隔的字符串,例如:

GET /_search

{

“query”: {

“simple_query_string” : {

“query” : “foo | bar + baz*”,

“flags” : “OR|AND|PREFIX”

}

}

}

可用的flag的列表如下:ALL, NONE, AND, OR, NOT, PREFIX, PHRASE, PRECEDENCE, ESCAPE, WHITESPACE, FUZZY, NEAR, and SLOP。

7.2 使用示例

public static void testSimpleQueryString_Query() {

RestHighLevelClient client = EsClient.getClient();

try {

SearchRequest searchRequest = new SearchRequest();

searchRequest.indices(“esdemo”);

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

sourceBuilder.query(

QueryBuilders.simpleQueryStringQuery(“brown -fox”)

);

searchRequest.source(sourceBuilder);

SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);

System.out.println(result);

} catch (Throwable e) {

e.printStackTrace();

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

ourceBuilder();

sourceBuilder.query(

QueryBuilders.simpleQueryStringQuery(“brown -fox”)

);

searchRequest.source(sourceBuilder);

SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);

System.out.println(result);

} catch (Throwable e) {

e.printStackTrace();

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-Q7XMXaOa-1710784450677)]
[外链图片转存中…(img-xRMvKAcA-1710784450677)]
[外链图片转存中…(img-qCIuJgJH-1710784450678)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-DaE2lHhS-1710784450678)]

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/485913
推荐阅读
相关标签
  

闽ICP备14008679号