Elasticsearch实战——高级查询

Elasticsearch实战——高级查询

文章目录

  • Elasticsearch实战——高级查询
    • 1. 复合查询
      • 1.1 constant_score
      • 1.2 bool query
      • 1.3 dis_max query
      • 1.4 function_score query
      • 1.5 boosting query
    • 2. 嵌套查询
      • 2.1 父子查询
        • 2.1.1 创建父子关系索引
        • 2.2.2 添加关系文档
        • 2.2.3 查询店铺下的商品
        • 2.2.4 查询商品属于哪个店铺
    • 3. 关注我

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查询可以把任意多个简单的查询组合在一起,使用mustshouldmust_notfilter选项表示简单查询之间的逻辑,每个选项都可以出现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.5 boosting query

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

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

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

{
    "query":{
        "boosting":{
            "positive":{
                "match":{
                    "title":"java"
                }
            },
            "negative":{
                "range":{
                    "publishAt":{
                        "lte":"2018-01-01"
                    }
                }
            },
            "negative_boost":0.2
        }
    }
}

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_typestoreid

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);

3. 关注我

搜索微信公众号:java架构强者之路
在这里插入图片描述

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