ES script
生成计算/动态字段(field)
- 使用场景
- es中只保存了人的出生年月,年龄是没保存,查询时需要动态生成,那么可以用script语句来来计算生成
- 使用文档
- https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html#request-body-search-script-fields
- https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html
- https://www.elastic.co/guide/en/elasticsearch/painless/current/painless-field-context.html
自定义过滤条件(filter)
- 使用场景
- 查询时要过滤“身高 + 体重 > 350”的人,要表示这种依赖计算值的过滤条件,无法用常规的query dsl来实现
- 使用文档
- https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-script-query.html
- The script query is typically used in a filter context. This script must return a boolean value, true or false.
- * https://www.elastic.co/guide/en/elasticsearch/painless/current/painless-filter-context.html
- context不支持_source,只支持_doc,意味着script中不能引用nested的数据,如果不做任何处理,无法实现以下搜索:在上市公司担任CFO超过5年的Talent
- 由于访问_source代价特别高,在filter阶段访问相当于全文查询,肯定是很慢的,因此官方禁止掉了,推荐的方式是访问doc,或者把nested的数据先进行预先计算,这样query dsl可以直接使用
- https://discuss.elastic.co/t/help-for-painless-iterate-nested-fields/162394
- 建议是把需要的信息预先index出来,在查询时直接使用,免去了查询时的计算带来的性能损耗
- https://discuss.elastic.co/t/painless-access-params-source-in-script-filter-in-6-1/115449/6
- Accessing source is very slow. I would think with analytics performance would be very important. Regardless, it was never intentional to allow access to source from search scripts in painless. It was simply a side effect of giving access for script fields, which we are now correcting with the separation of script contexts.
- https://discuss.elastic.co/t/scripted-filter-on-nested-field/27162
- https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-script-query.html
自定义权重(score)
- 使用场景
- 在没有任何干涉下,score计算只是由关键词的匹配的程度来决定,使用function-score-query,可以在原本搜索结果中,把一些符合条件的搜索结果进行权重增加,从而达到返回时顺序更靠前的效果。例如:查询到了一批有关键字为“Alex”的talent,我们可以把结果中曾担任过CEO的“Alex”进行提权,使他们返回结果过更靠前;相当于我们的搜索过程做了三层的事情
- filter
- 把所有数据进行一次过滤,例如:age > 35 && isActive = true
- search / keyword match
- 把fitler中得到的数据进行keyword match,有符合keyword的结果才返回,例如:firstname或lastname里面,带有“Alex”的结果
- scoring
- 把上面返回的结果重新计算score,例如:把在上市公司担任过CEO的talnet权重增加,排在返回结果的更前面
- filter
- 参考appbase.io的query rule,https://docs.appbase.io/docs/search/Rules/,可以设计一个关键词库,如果用户输入的词在关键词库有中存在,则对满足某个添加的搜索结果进行提权,例如:如果搜索关键词中包含google,则把chromebook的结果进行提权,达到营销的目的
- 在没有任何干涉下,score计算只是由关键词的匹配的程度来决定,使用function-score-query,可以在原本搜索结果中,把一些符合条件的搜索结果进行权重增加,从而达到返回时顺序更靠前的效果。例如:查询到了一批有关键字为“Alex”的talent,我们可以把结果中曾担任过CEO的“Alex”进行提权,使他们返回结果过更靠前;相当于我们的搜索过程做了三层的事情
- 使用文档
自定义排序(sort)
- 使用场景
- 想要进行排序的字段,不是mapping中存在的字段,而是需要靠动态计算出来的字段,例如:按照“年龄 + 体重”的计算值进行倒序排序
- 自定义sort和自定义score有点类似,但是sort的影响更加粗暴,直接把结果按照某个结果进行排序了,而score则可能是有好几个条件,带着不同权重计算得到score后,再按照score进行排序
- 使用文档
script lang
- expression
- js单行表达式语法,只能写单行的计算表达式,并且只能访问_doc里的数据(不能访问nested数据),功能比较局限
- 文档见:https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-expression.html
- painless
- java语言的子集,可以写出完整的多行代码,在不同的使用场景下(field、filter、score、sort),有不同的context
- 文档见:https://www.elastic.co/guide/en/elasticsearch/painless/7.5/painless-guide.html