我使用elasticsearch版本8.10。我写了一个脚本来检查输入字段'资历'有足够的条件搜索结果。
下面是我的demo index:
PUT target_index
{
"mappings": {
"properties": {
"targetoperator": { "type": "keyword" },
"targetvalue": {
"type": "float"
}
}
}
}
字符串
然后,我在上面创建一个文档:
PUT target_index/_doc/1
{
"targetoperator": [">"],
"targetvalue": [4]
}
型
我在上面运行脚本:
GET target_index/_search
{
"query": {
"script": {
"script": {
"lang": "painless",
"source": """
double userCriteria = params.userTarget.seniority;
if (doc['targetoperator'].length > 0) {
for (int i = 0; i < doc['targetoperator'].length; ++i) {
if (doc['targetoperator'][i] == "<=") {
if (!(userCriteria <= doc['targetvalue'][i])) {
return false;
}
} else if (doc['targetoperator'][i] == ">") {
if (!(userCriteria > doc['targetvalue'][i])) {
return false;
}
} else if (doc['targetoperator'][i] == "==") {
if (!(userCriteria == doc['targetvalue'][i])) {
return false;
}
}
}
}
return true;
""",
"params": {
"userTarget": {
"gender": "male",
"seniority": 5
}
}
}
}
},
"_source": [
"targetoperator",
"targetvalue"
]
}
型
运行查询后,我发现返回的结果是document = 1。但我再次更新document = 1:
PUT target_index/_doc/1
{
"targetoperator": [">", "<="],
"targetvalue": [4, 8]
}
型
我再次运行脚本查询。没有找到匹配的结果。
如果这是正确的,它将返回document = 1,因为资历= 5 > 4,5 <= 8
1条答案
按热度按时间xj3cbfub1#
这里有几个问题。
由于所有条件之间都需要AND逻辑,因此需要更改脚本,使其不立即返回true/false,而是将其存储到变量(例如
result
)中,如下所示:字符串
然而,我们还没有完成,因为您的目标 * doc值数组并没有按照您指定的方式存储,而是按照字典顺序存储。
运行以下查询显示:
型
返回
型
正如你所看到的,运算符的顺序不同,即
<=
在>
之前。因此,即使修改了逻辑,它也不会工作。你需要以不同的方式存储你的条件,使用
object
数组会遇到同样的问题,因为对象字段是扁平的。使用nested
会有所帮助,但脚本将在每个嵌套条件的上下文中进行评估,你需要一些后处理逻辑来确保所有条件匹配,即在这种情况下,您需要在应用程序代码中验证嵌套匹配的doc_count是否为2。由于性能问题,不鼓励使用脚本,除此之外,我强烈建议您修改应用条件的方式。我可以建议使用search templates,它可以帮助您构建非常强大的查询。