下面是我的索引文档
{
"defaultBoostValue":1.01,
"boostDetails": [
{
"Type": "Type1",
"value": 1.0001
},
{
"Type": "Type2",
"value": 1.002
},
{
"Type": "Type3",
"value": 1.0005
}
]
}
我想根据传递的值应用boost,所以假设我通过Type1,那么应用的boost将是1.0001,如果Type1不存在,那么它将使用defaultBoostValue下面是我的查询,工作,但相当慢,有没有办法进一步优化它
原始问题上面的查询工作,但很慢,因为我们使用的是_source
{
"query": {
"function_score": {
"boost_mode": "multiply",
"functions": [
"script_score": {
"script": {
"source": """
double findBoost(Map params_copy) {
for (def group : params_copy._source.boostDetails) {
if (group['Type'] == params_copy.preferredBoostType ) {
return group['value'];
}
}
return params_copy._source['defaultBoostValue'];
}
return findBoost(params)
""",
"params": {
"preferredBoostType": "Type1"
}
}
}
}
]
}
}
}
我已经删除了没有动态映射的条件,如果改变boostDetails映射的结构可以帮助,那么我很好,但请解释它如何可以帮助和更快地查询,也请给出映射类型和修改的结构,如果答案包含修改映射。
使用动态映射(大量字段)
与你最初的问题相比,你似乎调整了文档结构。
上面的查询被认为是针对嵌套字段的,由于性能原因,这些字段在脚本中不能容易地迭代。话虽如此,上面是一个更慢的解决方案,它访问文档的_source
并迭代其内容。但请记住,它是,不建议使用访问脚本中的_source
!如果你的文档不再嵌套,你可以访问所谓的文档值,这对查询时的访问更优化:
{
"query": {
"function_score": {
...
"functions": [
{
...
"script_score": {
"script": {
"lang": "painless",
"source": """
try {
if (doc['boost.boostType.keyword'].value == params.preferredBoostType) {
return doc['boost.boostFactor'].value;
} else {
throw new Exception();
}
} catch(Exception e) {
return doc['fallbackBoostFactor'].value;
}
""",
"params": {
"preferredBoostType": "Type1"
}
}
}
}
]
}
}
}
从而加快函数分数查询。
使用有序值列表的备选方案
由于嵌套迭代很慢,动态映射会破坏索引,您可以将您的提升存储在每个文档的标准化有序列表中:
"boostValues": [1.0001, 1.002, 1.0005, ..., 1.1]
,并在构建查询的后端跟踪相应的boost类型的顺序:
var boostTypes = ["Type1", "Type2", "Type3", ..., "TypeN"]
也就是n个热向量
然后,当您构造Elasticsearch查询时,您将查找数组索引基于boostType
的boostValues
的索引,并将该数组索引传递给上面的脚本查询,该脚本查询将访问相应的boostValues
doc-value。
这保证比_source
访问快。但是需要始终保持boostTypes
和boostValues
同步——最好只追加(当你添加新的boostTypes
时,列表在一个维度上增长)。