ElasticSearch的查询结果在使用match分词后,es的引擎会对搜索结果进行打分,然后通过分数的高低来进行排序,具体的打分算法涉及到Lucene的计分函数(Lucene’s Practical Scoring Function)、查询时权重提升(Query-Time Boosting)等两种方式来影响查询的分数。这里不展开关于Lucene的计分函数的内容,仅仅用来说明如何利用查询时权重提升中的一种方法,function score来改变查询。
具体业务需求如下,从前端根据关键词搜索文章,关键词会匹配标题、正文内容、额外要求三个不同的mapping字段,这个三个字段均要求全文分词,其中标题需要占用高比重。该需求简单的使用multi_match就可以实现,其查询DSL如下:
GET index/indexMapping/_search
{
"_source": {
"includes": ["NOTICE_NAME","NOTICE_SEND_TIME"],
"excludes": ["NOTICE_CONTENT","BIDDING_REQUIREMENT"]
},
"from": 0,
"size": 100,
"query": {
"multi_match": {
"query": "北京农商银行北京农民合作社信用评价系统项目 采购公告",
"fields": ["NOTICE_NAME^5","NOTICE_CONTENT","BIDDING_REQUIREMENT"]
}
}
}
通过如上的查询可以获取记录,但是因为es会自动打分,所以除了精确匹配标题的分数最高在第一条外,有可能会搜素到比较老的数据,业务上要求除了score外需要考虑时间因素,但是不能利用sort方法去改变,因此需要设计function scrore query来进行调优。
GET index/indexMapping/_search
{
"query": {
"function_score": {
"query": {
"multi_match": {
"query": "北京农商银行北京农民合作社信用评价系统项目",
"fields": ["NOTICE_NAME^5","NOTICE_CONTENT","BIDDING_REQUIREMENT"]
}
},
"score_mode": "max",
"functions": [
{
"filter": {
"match_phrase": {
"NOTICE_NAME": "北京农商银行北京农民合作社信用评价系统项目" }
},
"weight": 10
},
{
"gauss": {
"NOTICE_SEND_TIME": {
"origin": "2019-07-29",
"scale": "1d",
"offset": "15d",
"decay" : 0.7
}
}
}
]
}
},
"_source": {
"includes": ["NOTICE_NAME","NOTICE_SEND_TIME"],
"excludes": ["NOTICE_CONTENT","BIDDING_REQUIREMENT"]
},
"from": 0,
"size": 10
}
构造两个function,第一个用match_phrase做精确匹配标题,给与10倍的权重,对于时间,利用ES gass函数进行对于当前时间的范围调优。以上能够得到较为优秀的结果。
ES打分机制将逐步展开。
本文为Lokie.Wang原创文章,转载无需和我联系,但请注明来自lokie博客http://lokie.wang