elasticsearch 5.2.2 学习笔记之源码阅读11-脚本模块(ScriptModule)总览之脚本字段与自定义评分
概述
脚本模块(ScriptModule)总览之脚本字段与自定义评分
{
"query": {
"match_all": {}
},
"script_fields": {
"total_goals": {
"script": {
"lang": "painless",
"inline": "int total = 0; for (int i = 0; i < doc['goals'].length; ++i) { total += doc['goals'][i]; } return total;"
}
},
"test1": {
"script": "params['_source']['last']"
},
"max_goals": {
"script": {
"lang": "expression",
"inline": "doc['goals'].max()"
}
}
}
}
{
"query": {
"function_score": {
"script_score": {
"script": {
"lang": "painless",
"inline": "int total = 0; for (int i = 0; i < doc['goals'].length; ++i) { total += doc['goals'][i]; } return total;"
}
}
}
}
}
{
"query": {
"match_all": {}
},
"sort": {
"_script": {
"type": "string",
"order": "asc",
"script": {
"lang": "painless",
"inline": "doc['first.keyword'].value + ' ' + doc['last.keyword'].value"
}
}
}
}
核心接口与类
- 使用AbstractComponent和AbstractLifecycleComponent管理核心组件的配置与生命周期
- AbstractComponent
- AbstractLifecycleComponent
- ScriptService(脚本服务的支持类)
- LifecycleComponent
- ScriptPlugin(脚本插件,用于加载脚本执行服务/本地脚本工厂/脚本上下文)
- PainlessPlugin(painless语言支持的插件)
- ScriptModule(用于管理ScriptSettings和ScriptService)
- ScriptEngineService(脚本引擎的接口,定义编译脚本/执行编译脚本/将编译脚本用于搜索等)
- PainlessScriptEngineService(painless语言支持)
- PythonScriptEngineService(python语言支持)
- GroovyScriptEngineService(groovy语言支持)
- ScriptSettings(脚本相关的设置信息)
- CompiledScript
- SearchScript
- node启动查看 https://blog.youkuaiyun.com/undergrowth/article/details/82840411
- 通过PluginsService(https://blog.youkuaiyun.com/undergrowth/article/details/82857089)加载modules目录下的lang-painless插件,即加载PainlessPlugin用于构建PainlessScriptEngineService
- 再看搜索的流程参看https://blog.youkuaiyun.com/undergrowth/article/details/83001430 是如何解析script_fields,里面的脚本是如何执行返回到原有文档中的?
- 在前面搜索里面提到过,在SearchSourceBuilder#parseXContent的时候,解析出List scriptFields的脚本语言(里面调用Script#parse进行解析)
- 查询分两步,在第一步query阶段时候,SearchService#executeQueryPhase执行的时候创建SearchContext,在SearchService#parseSource将SearchSourceBuilder转为DefaultSearchContext,同时利用scriptService.search将ScriptField转化为SearchScript供后续使用
- 这里分为compile(利用ScriptEngineService的实现类转换Script为CompiledScript)和search(将CompiledScript转为SearchScript),根据node启动时候的插件机制和传递的lang,这里指的是实现类是PainlessScriptEngineService
- 第二步,在fetch阶段的时候,FetchPhase#execute执行完成后,会遍历FetchSubPhase集合,进行获取子阶段处理,这里看ScriptFieldsFetchSubPhase#hitExecute遍历query阶段解析出来的ScriptFieldsContext.ScriptField,进行脚本的运行leafScript.unwrap(leafScript.run()),这里调用painless.ScriptImpl#run执行脚本,然后修改hitContext.hit().fields().put(scriptField.name(), hitField),完成脚本字段的解析
以 自定义评分 为例讲解加载过程(待更新)