es之高级查询

1. 复合查询

复合查询就是把一些简单查询组合在一起实现更复杂的查询需求,除此之外复合查询还可以控制另外一个查询的行为。

1.1 constant_score

constant_score query可以包装一个其他类型的查询,并返回匹配过滤器中的查询条件其具有相同评分的文档。当我们不关心检索词频率对搜索结果排序的影响时,可以使用constant_score将查询语句query或者过滤语句filter包装起来。

示例如下:

{

"query":{

"constant_score":{

"filter":{

"term":{

"city":"北京市"

}

}

}

}

}

java示例如下:

MatchQueryBuilder query = QueryBuilders.matchQuery("title", "新闻").minimumShouldMatch("90%");

QueryBuilders.constantScoreQuery(query).boost(3.0f);

1.2 bool query

bool查询可以把任意多个简单的查询组合在一起,使用must、should、must_not、filter选项表示简单查询之间的逻辑,每个选项都可以出现0次到多次,它们的含义如下:

must:文档必须匹配must选项下的查询条件,相挡于逻辑运算符 AND。

should:文档可以匹配should选项下的查询条件也可以不匹配,相挡于逻辑运算的OR。

must_not:与must相反,匹配该选项下的查询条件的文档不会被返回。

filter:和must一样,匹配filter选项下的查询条件的文档才会被返回,但是filter不评分,只起到过滤功能。

示例如下:

{

"query":{

"bool":{

"must":[

{

"match":{

"title":"共享单车"

}

},

{

"term":{

"district":"昌平区"

}

}

],

"should":[

{

"match":{

"address":"朝阳区"

}

}

]

}

}

}

1.3 dis_max query

dis_max query与bool query有一定联系也有一定区别,dis_max query支持多并发查询,可返回与任意查询条件子句匹配的文档类型。与bool查询可以将所有匹配查询的分数相结合的方式不同,dis_max查询只使用最佳查询条件的分数。

{

"query":{

"dis_max":{

"tie_breaker":0.7,

"boost":1.2,

"queries":[

{

"match":{"address":"北京朝阳区"}

},

{

"match":{

"title":"北京朝阳区"

}

}

]

}

}

}

1.4 function_score query

function_score query可以修改查询的文档得分,这个查询在有些情况下非常有用,比如通过评分函数计算文档得分代价较高,可以改用过滤器加自定义评分函数的方式来取代传统的评分方式。

使用function_score query,用户需定义一个查询和一至多个评分函数,评分函数会对查询到的每个文档分别计算得分。

{

"query": {

"function_score": {

"query": {

"function_score": {

"query": {

"match": {

"title": "java编程"

}

},

"functions": [

{

"field_value_factor": {

"field": "price",

"factor": 0.1,

"modifier": "ln1p"

}

}

],

"score_mode": "multiply",

"max_boost": 10,

"boost": 1

}

},

"functions": [],

"score_mode": "multiply",

"boost_mode": "sum",

"max_boost": 10,

"boost": 1

}

}

}

java示例如下:

MatchPhraseQueryBuilder titleQuery = QueryBuilders.matchPhraseQuery("title", "java编程");

FieldValueFactorFunctionBuilder factor = ScoreFunctionBuilders.fieldValueFactorFunction("price").modifier(FieldValueFactorFunction.Modifier.LN1P).factor(0.1f);

FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = {

new FunctionScoreQueryBuilder.FilterFunctionBuilder(factor)

};

FunctionScoreQueryBuilder functionScoreQuery = QueryBuilders.functionScoreQuery(titleQuery,filterFunctionBuilders);

FunctionScoreQueryBuilder query = QueryBuilders.functionScoreQuery(functionScoreQuery).boostMode(CombineFunction.SUM);

1

2

3

4

5

6

7

评分函数详解

1.5 boosting query

boosting查询用于需要对两个查询的评分进行调整的场景,boosting查询会把两个查询封装在一起并降低其中一个查询的评分。

boosting查询包括positive,negative和negative_boost三部分,positive中的查询评分保持不变,negative中的查询会降低文档评分,negative_boost指明negative中降低的权值。

查询title为java的书籍,出版时间在2018年之前的排在后面。

{

"query":{

"boosting":{

"positive":{

"match":{

"title":"java"

}

},

"negative":{

"range":{

"publishAt":{

"lte":"2018-01-01"

}

}

"negative_boost":0.2

}

}

}

13

java示例如下:

MatchPhraseQueryBuilder titleQuery = QueryBuilders.matchPhraseQuery("title", "java");

RangeQueryBuilder publishAt = QueryBuilders.rangeQuery("publishAt").lte("2018-01-01");

QueryBuilders.boostingQuery(titleQuery,publishAt).negativeBoost(0.2f);

2. 嵌套查询

2.1 父子查询

这里以店铺和商品为例,它们属于不同的的类型,相当于数据库中的两张表,如果想把店铺和它们经营的商品关联起来就需要告诉ES文档之间的父子关系,这里指定一个字段store2product来维护这种关系,该字段的类型为join,并指定它们的关系。

2.1.1 创建父子关系索引

PUT store

{

"mappings": {

"properties": {

"name": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_smart"

},

"store2product": {

"type": "join",

"relations": {

"storeid": "productid"

}

}

}

}

}

2.2.2 添加关系文档

添加父文档(店铺),并指定父字段

PUT store/1

{

"name":"创实食品专营店",

"store2product":"storeid"

}

添加子文档(商品),并且需要子文档和父文档在同一个分片,所以需要指定路由id为父id

PUT store/2?routing=1

{

"name":"创实 原味酸梅汤 速溶酸梅粉 冲饮果汁饮料1000g 酸梅汤原料",

"store2product":{

"name":"productid",

"parent":"1"

}

}

2.2.3 查询店铺下的商品

使用has_parent查询,并指定parent_type为storeid

GET store/_search

{

"query": {

"has_parent": {

"parent_type": "storeid",

"query": {

"match": {

"name": "食品专营店"

}

}

}

}

}

java示例如下:

MatchQueryBuilder nameQuery = QueryBuilders.matchQuery("name", "食品专营店");

HasParentQueryBuilder hasParentQueryBuilder = new HasParentQueryBuilder("storeid",nameQuery,true);

2.2.4 查询商品属于哪个店铺

使用has_child查询,并指定一个type字段为productid

GET store/_search

{

"query": {

"has_child": {

"type":"productid",

"query": {

"match": {

"name": "原味酸梅汤"

}

}

}

}

}

java示例如下:

MatchQueryBuilder nameQuery = QueryBuilders.matchQuery("name", "原味酸梅汤");

HasChildQueryBuilder hasChildQueryBuilder = new HasChildQueryBuilder("productid",nameQuery, ScoreMode.None);

文章来源:https://blog.csdn.net/dwjf321/article/details/103934964

发布了277 篇原创文章 · 获赞 65 · 访问量 38万+

猜你喜欢

转载自blog.csdn.net/ailiandeziwei/article/details/104709970