关于ES中Function_Score在自定义打分中的应用

应用背景

现在有许多商品需要在商品列表中进行排序展示,排序要求使用ES并且尽量一次性查出来,有要求如下:
  • 重点商品,收藏商品,优质商品,普通商品的顺序展出
  • 在同一类商品发生冲突时,按照自主产品,非自主产品进行展出(是否自主产品是一个集合,只有集合里面有7才属于自主产品,没有7则属于非自主产品)
  • 如果继续发生冲突 按照商品录入时间展出
  • 最后用id来进行兜底
  • 优质商品首先根据商品的等级来排序,然后才走第二行

ES中使用到的字。

id (商品的序列号),
create_time(创建商品时间) ,
one_hand_commodity(是否是优质商品) ,
commodity_level , (商品等级4个级别 S,A,B,C)
commodity_list(商品属性,是否是自主产品) ,
publish_time , (商品上架时间)

难点

在这次应用中,有几个难点
1、优质商品有着自己的排序特点,不能使用sort来进行总体排序。
2、重点商品以及收藏商品需要置顶放在最高。
3、就是在原有实现方案基础上进行代码的合并

分析

在不能使用sort的情况下,以及优质商品的独特性,我们在ES官网给出了我们提示,使用得分,自定义得分以及funcationScore来实现评分排序。
由于优质商品有着独特的排序情况,我们将 one_hand_commodity(是否是优质商品)与commodity_level , (商品等级4个级别 S,A,B,C)俩字段,将他们满足优质商品同时满足商品等级的氛围不同的权重,用weight来赋值。

"function_score": {
            "query": {
              "term": {
                "one_hand_commodity: {
                  "value": "1",
                  "boost": 1
                }
              }
            },
            "functions": [
              {
                "filter": {
                  "term": {
                    "commodity_level": {
                      "value": 1,
                      "boost": 1
                    }
                  }
                },
                "weight": 96
              },
              {
                "filter": {
                  "term": {
                    "commodity_level": {
                      "value": 2,
                      "boost": 1
                    }
                  }
                },
                "weight": 48
              },
              {
                "filter": {
                  "term": {
                    "commodity_level": {
                      "value": 3,
                      "boost": 1
                    }
                  }
                },
                "weight": 24
              },
              {
                "filter": {
                  "term": {
                    "commodity_level": {
                      "value": 4,
                      "boost": 1
                    }
                  }
                },
                "weight": 12
              }
            ],
            "score_mode": "sum",
            "boost_mode": "replace",
          }

其中的score_mode 的作用是在functions所有命中的filter,都采用sum即累加的方式,而boost_mode 是整个functionScore与外面的query采用replace,替换的方式进行积分。
像 在集合中是否存在7,可以使用terms来进行命中

 "function_score": {
            "query": {
              "bool": {
                "must_not": [
                  {
                    "term": {
                      "commodity_list": {
                        "value": "7",
                        "boost": 1
                      }
                    }
                  }
                ],
                "adjust_pure_negative": true,
                "boost": 1
              }
            },
            "functions": [
              {
                "filter": {
                  "bool": {
                    "must_not": [
                      {
                        "term": {
                          "commodity_list": {
                            "value": "7",
                            "boost": 1
                          }
                        }
                      }
                    ],
                    "adjust_pure_negative": true,
                    "boost": 1
                  }
                },
                "weight": 3
              }
            ],
            "score_mode": "sum",
            "boost_mode": "replace",
            "boost": 1
          }

而对于重点商品以及收藏商品就可以在mysql中关联查询出来,在es语句中进行赋值

"function_score": {
            "query": {
              "terms": {
                "id": [
                  53507,
                  53628
                ],
                "boost": 1
              }
            },
            "functions": [
              {
                "filter": {
                  "terms": {
                    "id": [
                      53507,
                      53628
                    ],
                    "boost": 1
                  }
                },
                "weight": 192
              }
            ],
            "score_mode": "sum",
            "boost_mode": "replace",
            "boost": 1
          }

这样将优质商品的不同等级进行了不同的得分,最后就可以使用sort来进行排序。

  "sort": [
    {
      "_score": {
        "order": "desc"
      }
    },
    {
      "create_time": {
        "order": "desc"
      }
    },
    {
      "id": {
        "order": "desc"
      }
    }
  ],

ps:整个这次查询的weight设置,统一使用

前面所有weight和 < 现在需要赋值的weight
且最小只能从大于1开始,不能为1。

附:全部查询代码

{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "commodity_status": {
              "value": 2,
              "boost": 1
            }
          }
        },
        {
          "terms": {
            "id": [
              53507,
              53628,
              53656,
              53681
            ],
            "boost": 1
          }
        },
        {
          "term": {
            "is_delete": {
              "value": 0,
              "boost": 1
            }
          }
        }
      ],
      "should": [
        {
          "function_score": {
            "query": {
              "term": {
                "one_hand_commodity": {
                  "value": "1",
                  "boost": 1
                }
              }
            },
            "functions": [
              {
                "filter": {
                  "term": {
                    "commodity_level": {
                      "value": 1,
                      "boost": 1
                    }
                  }
                },
                "weight": 96
              },
              {
                "filter": {
                  "term": {
                    "commodity_level": {
                      "value": 2,
                      "boost": 1
                    }
                  }
                },
                "weight": 48
              },
              {
                "filter": {
                  "term": {
                    "commodity_level": {
                      "value": 3,
                      "boost": 1
                    }
                  }
                },
                "weight": 24
              },
              {
                "filter": {
                  "term": {
                    "commodity_level": {
                      "value": 4,
                      "boost": 1
                    }
                  }
                },
                "weight": 12
              }
            ],
            "score_mode": "sum",
            "boost_mode": "replace",
            "max_boost": 3.4028235e+38,
            "boost": 1
          }
        },
        {
          "function_score": {
            "query": {
              "term": {
                "one_hand_commodity": {
                  "value": "0",
                  "boost": 1
                }
              }
            },
            "functions": [
              {
                "filter": {
                  "term": {
                    "one_hand_commodity": {
                      "value": "0",
                      "boost": 1
                    }
                  }
                },
                "weight": 6
              }
            ],
            "score_mode": "sum",
            "boost_mode": "replace",
            "max_boost": 3.4028235e+38,
            "boost": 1
          }
        },
        {
          "function_score": {
            "query": {
              "term": {
                "commodity_list": {
                  "value": "7",
                  "boost": 1
                }
              }
            },
            "functions": [
              {
                "filter": {
                  "term": {
                    "commodity_list": {
                      "value": "7",
                      "boost": 1
                    }
                  }
                },
                "weight": 2
              }
            ],
            "score_mode": "sum",
            "boost_mode": "replace",
            "max_boost": 3.4028235e+38,
            "boost": 1
          }
        },
        {
          "function_score": {
            "query": {
              "bool": {
                "must_not": [
                  {
                    "term": {
                      "commodity_list": {
                        "value": "7",
                        "boost": 1
                      }
                    }
                  }
                ],
                "adjust_pure_negative": true,
                "boost": 1
              }
            },
            "functions": [
              {
                "filter": {
                  "bool": {
                    "must_not": [
                      {
                        "term": {
                          "commodity_list": {
                            "value": "7",
                            "boost": 1
                          }
                        }
                      }
                    ],
                    "adjust_pure_negative": true,
                    "boost": 1
                  }
                },
                "weight": 3
              }
            ],
            "score_mode": "sum",
            "boost_mode": "replace",
            "max_boost": 3.4028235e+38,
            "boost": 1
          }
        },
        {
          "function_score": {
            "query": {
              "terms": {
                "id": [
                  53507,
                  53628,
                  53656,
                  53681
                ],
                "boost": 1
              }
            },
            "functions": [
              {
                "filter": {
                  "terms": {
                    "id": [
                      53507,
                      53628,
                      53656,
                      53681
                    ],
                    "boost": 1
                  }
                },
                "weight": 192
              }
            ],
            "score_mode": "sum",
            "boost_mode": "max",
            "max_boost": 3.4028235e+38,
            "boost": 1
          }
        }
      ],
      "adjust_pure_negative": true,
      "boost": 1
    }
  },
  "sort": [
    {
      "_score": {
        "order": "desc"
      }
    },
    {
      "create_time": {
        "order": "desc"
      }
    },
    {
      "id": {
        "order": "desc"
      }
    }
  ],
  "track_total_hits": 2147483647
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
在Java使用Elasticsearch的Function Score API可以对搜索结果进行加权,以提高搜索结果的相关性。Function Score API提供了多种函数和算法,可以根据不同的需求进行调整。下面是Java代码关于Elasticsearch的Function Score API的详解。 1. Function Score Query Function Score Query是使用Function Score API的最基本方法。以下是一个简单的例子: ```java FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery() .add(QueryBuilders.matchQuery("name", "Bob"), ScoreFunctionBuilders.weightFactorFunction(2)) .add(QueryBuilders.matchQuery("age", "30"), ScoreFunctionBuilders.weightFactorFunction(3)) .scoreMode("sum"); SearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(functionScoreQueryBuilder) .build(); ``` 其,add方法添加了两个查询条件,分别是匹配name为Bob和age为30的记录,weightFactorFunction方法设置了权重因子,这里分别为2和3。scoreMode方法设置了计算分数的方式,这里为求和。 2. Decay Functions Decay Functions提供了一种根据距离或时间进行衰减的方法,可以用来实现地理位置搜索、时间搜索等功能。以下是一个地理位置搜索的例子: ```java FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery() .add(QueryBuilders.matchAllQuery(), ScoreFunctionBuilders.weightFactorFunction(1)) .add(ScoreFunctionBuilders .gaussDecayFunction("location", new GeoPoint(40.715, -74.011), "1km") .setDecay(0.5) .setOffset("1km") .setWeight(2)) .scoreMode("sum"); SearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(functionScoreQueryBuilder) .build(); ``` 其,gaussDecayFunction方法设置了衰减函数为高斯衰减函数,参数分别为字段名、心点、衰减半径。setDecay方法设置了衰减速率,这里为0.5。setOffset方法设置了衰减偏移量,这里为1km。setWeight方法设置了权重因子,这里为2。 3. Script Functions Script Functions可以使用脚本来自定义计算分数的逻辑,可以实现更加灵活的需求。以下是一个使用脚本计算分数的例子: ```java Script script = new Script(ScriptType.INLINE, "painless", "doc['age'].value * params.factor", Collections.singletonMap("factor", 2)); FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery() .add(QueryBuilders.matchAllQuery(), ScoreFunctionBuilders.weightFactorFunction(1)) .add(ScoreFunctionBuilders.scriptFunction(script)) .scoreMode("sum"); SearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(functionScoreQueryBuilder) .build(); ``` 其,script方法设置了脚本,使用了Painless语言,计算分数的逻辑为doc['age'].value * params.factor,其params.factor为参数,这里为2。 总之,Elasticsearch的Function Score API提供了多种函数和算法,可以根据不同的需求进行调整。在Java代码,可以使用FunctionScoreQueryBuilder和ScoreFunctionBuilders来构建查询条件和函数,实现对搜索结果的加权。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值