本文介绍复合条件查询,着重介绍其中的 固定分数查询 和 布尔查询。
先把示例文档数据再列一遍:
固定分数查询
什么叫固定分数查询?有什么用?通俗地说,当我们需要人为干预将查询搜索的分数_score的值设置为某个固定值时,就需要用到固定分数查询。关键词constant_score。
固定分数查询看起来简单,实际用起来却非常灵活,比如你电商产品,你可以提高某些商品的属性的评分,提高需要呈现给用户的商品的优先级,当然,它的使用场景远不止于此。
注意:固定分数查询不支持match,只支持filter。当然,filter下面可以match。filter会缓存结果数据。
下面是示例
这里我们全文搜索,url里直接_search,没索引。
POST http://localhost:9200/_search
{
"query":{
"constant_score":{
"filter":{
"match":{
"communityname": "滨江花园"
}
}
}
}
}
查询结果可以看到,所有的返回结果的分数都默认固定是1。
{
"took": 9,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 5,
"max_score": 1,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZD_9YoILHeA4gRvWC",
"_score": 1,
"_source": {
"communityname": "万科公园大道",
"city": "上海老闵行",
"age": 3,
"creationdate": "2015-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZFA5EoILHeA4gRvWF",
"_score": 1,
"_source": {
"communityname": "金地艺境(松江)",
"city": "上海松江区",
"age": 3,
"creationdate": "2015-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZEXNioILHeA4gRvWD",
"_score": 1,
"_source": {
"communityname": "万科白马花园",
"city": "上海莘闵别墅区",
"age": 15,
"creationdate": "2003-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLDhHMpoILHeA4gRvV7",
"_score": 1,
"_source": {
"communityname": "世茂滨江花园",
"city": "上海",
"age": 9,
"creationdate": "2009-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZCaoSoILHeA4gRvV-",
"_score": 1,
"_source": {
"communityname": "万科朗润园",
"city": "上海",
"age": 12,
"creationdate": "2006-01-01 00:00:00"
}
}
]
}
}
我们还可以如下设置固定分数查询的分数值为特定值,需要使用boost关键词:
POST http://localhost:9200/_search
{
"query":{
"constant_score":{
"filter":{
"match":{
"communityname": "滨江花园"
}
},
"boost":2
}
}
}
返回结果:
{
"took": 11,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 5,
"max_score": 2,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZD_9YoILHeA4gRvWC",
"_score": 2,
"_source": {
"communityname": "万科公园大道",
"city": "上海老闵行",
"age": 3,
"creationdate": "2015-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZFA5EoILHeA4gRvWF",
"_score": 2,
"_source": {
"communityname": "金地艺境(松江)",
"city": "上海松江区",
"age": 3,
"creationdate": "2015-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZEXNioILHeA4gRvWD",
"_score": 2,
"_source": {
"communityname": "万科白马花园",
"city": "上海莘闵别墅区",
"age": 15,
"creationdate": "2003-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLDhHMpoILHeA4gRvV7",
"_score": 2,
"_source": {
"communityname": "世茂滨江花园",
"city": "上海",
"age": 9,
"creationdate": "2009-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZCaoSoILHeA4gRvV-",
"_score": 2,
"_source": {
"communityname": "万科朗润园",
"city": "上海",
"age": 12,
"creationdate": "2006-01-01 00:00:00"
}
}
]
}
}
布尔查询
Bool查询对应Lucene中的BooleanQuery,它由一个或者多个子句组成,每个子句都有特定的类型。
must
返回的文档必须满足must子句的条件,并且参与计算分值
filter
返回的文档必须满足filter子句的条件。但是不会像Must一样,参与计算分值
should
返回的文档可能满足should子句的条件。在一个Bool查询中,如果没有must或者filter,有一个或者多个should子句,那么只要满足一个就可以返回。minimum_should_match
参数定义了至少满足几个子句。
must_nout
返回的文档必须不满足must_not定义的条件。
如果一个查询既有filter又有should,那么至少包含一个should子句。
bool查询也支持禁用协同计分选项disable_coord。一般计算分值的因素取决于所有的查询条件。
bool查询也是采用more_matches_is_better的机制,因此满足must和should子句的文档将会合并起来计算分值。
示例:
should
POST http://localhost:9200/_search
{
"query":{
"bool":{
"should":[
{
"match":{
"communityname": "滨江花园"
}
}
,
{
"match":{
"city": "上海浦东航头"
}
}
]
}
}
}
查询结果如下:可以看出should中的match条件列表中各个条件之间是或的关系。
附带一提,city是keyword类型,所以需要完全匹配;community是text类型,所以是文本匹配。
{
"took": 8,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 6,
"max_score": 5.9040833,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLDhHMpoILHeA4gRvV7",
"_score": 5.9040833,
"_source": {
"communityname": "世茂滨江花园",
"city": "上海",
"age": 9,
"creationdate": "2009-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZEXNioILHeA4gRvWD",
"_score": 2.3456469,
"_source": {
"communityname": "万科白马花园",
"city": "上海莘闵别墅区",
"age": 15,
"creationdate": "2003-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZFV2doILHeA4gRvWG",
"_score": 1.2039728,
"_source": {
"communityname": "金地艺华年",
"city": "上海浦东航头",
"age": 5,
"creationdate": "2013-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZCaoSoILHeA4gRvV-",
"_score": 1.1690899,
"_source": {
"communityname": "万科朗润园",
"city": "上海",
"age": 12,
"creationdate": "2006-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZD_9YoILHeA4gRvWC",
"_score": 1.0751344,
"_source": {
"communityname": "万科公园大道",
"city": "上海老闵行",
"age": 3,
"creationdate": "2015-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZFA5EoILHeA4gRvWF",
"_score": 1.0751344,
"_source": {
"communityname": "金地艺境(松江)",
"city": "上海松江区",
"age": 3,
"creationdate": "2015-01-01 00:00:00"
}
}
]
}
}
must
如果需要各个match条件必须全部满足,可以用must。
POST http://localhost:9200/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"communityname": "滨江花园"
}
}
,
{
"match":{
"city": "上海莘闵别墅区"
}
}
]
}
}
}
结果:
{
"took": 98,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 4.338077,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZEXNioILHeA4gRvWD",
"_score": 4.338077,
"_source": {
"communityname": "万科白马花园",
"city": "上海莘闵别墅区",
"age": 15,
"creationdate": "2003-01-01 00:00:00"
}
}
]
}
}
(本文出自ochina博主happybks的博文https://my.oschina.net/happyBKs/blog/1800666)
must_not
must_not的意思是一个都不能符合match:
POST http://localhost:9200/_search
{
"query":{
"bool":{
"must_not":[
{
"match":{
"communityname": "万科金地"
}
},
{
"match":{
"communityname": "中海"
}
}
]
}
}
}
查询结果:
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 4,
"max_score": 1,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZF4FAoILHeA4gRvWI",
"_score": 1,
"_source": {
"communityname": "保利西子湾",
"city": "上海松江大学城",
"age": 10,
"creationdate": "2008-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZHsN6oILHeA4gRvWO",
"_score": 1,
"_source": {
"communityname": "象屿鼎城",
"city": "上海浦东川沙",
"age": 5,
"creationdate": "2013-01-01"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLDhHMpoILHeA4gRvV7",
"_score": 1,
"_source": {
"communityname": "世茂滨江花园",
"city": "上海",
"age": 9,
"creationdate": "2009-01-01 00:00:00"
}
},
{
"_index": "rent",
"_type": "community",
"_id": "AWLZGGD2oILHeA4gRvWJ",
"_score": 1,
"_source": {
"communityname": "保利艾庐",
"city": "上海浦东新区周浦镇",
"age": 3,
"creationdate": "2015-01-01"
}
}
]
}
}
追加filter操作
我们还可以在must、should等的基础上追加filter操作:
{
"query":{
"bool":{
"must":[
{
"match":{
"communityname": "滨江花园"
}
}
,
{
"match":{
"city": "上海"
}
}
],
"filter":{
"term":{
"age":12
}
}
}
}
}
查询结果:
{
"took": 122,
"timed_out": false,
"_shards": {
"total": 3,
"successful": 3,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 2.6506944,
"hits": [
{
"_index": "rent",
"_type": "community",
"_id": "AWLZCaoSoILHeA4gRvV-",
"_score": 2.6506944,
"_source": {
"communityname": "万科朗润园",
"city": "上海",
"age": 12,
"creationdate": "2006-01-01 00:00:00"
}
}
]
}
}