我试图弄清楚如何解决我对ES 5.6索引遇到的两个问题。
"mappings": {
"my_test": {
"properties": {
"Employee": {
"type": "nested",
"properties": {
"Name": {
"type": "keyword",
"normalizer": "lowercase_normalizer"
},
"Surname": {
"type": "keyword",
"normalizer": "lowercase_normalizer"
}
}
}
}
}
}
我需要创建两个单独的脚本过滤器:
1-滤波器文档,其中员工数组的大小为== 3
2-滤波器文档,其中数组的第一个元素具有"名称" ==" John"
我试图迈出一些第一步,但是我无法迭代列表。我总是有一个空指针异常错误。
{
"bool": {
"must": {
"nested": {
"path": "Employee",
"query": {
"bool": {
"filter": [
{
"script": {
"script" : """
int array_length = 0;
for(int i = 0; i < params._source['Employee'].length; i++)
{
array_length +=1;
}
if(array_length == 3)
{
return true
} else
{
return false
}
"""
}
}
]
}
}
}
}
}
}
正如Val所注意到的,您无法访问Elasticsearch最近版本中脚本查询中文档的_source
。但是Elasticsearch允许您在"得分上下文"中访问此_source
。
因此,可能的解决方法(但是您需要谨慎性能(是使用脚本分数与查询中的min_score结合在一起。
您可以在此堆栈溢出的查询文档中找到此行为的示例。
中的嵌套字段值的总和。在您的情况下,这样的查询可以完成工作:
POST <your_index>/_search
{
"min_score": 0.1,
"query": {
"function_score": {
"query": {
"match_all": {}
},
"functions": [
{
"script_score": {
"script": {
"source": """
if (params["_source"]["Employee"].length === params.nbEmployee) {
def firstEmployee = params._source["Employee"].get(0);
if (firstEmployee.Name == params.name) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
""",
"params": {
"nbEmployee": 3,
"name": "John"
}
}
}
}
]
}
}
}
应该在参数中设置员工数量和名字的数量,以避免对此脚本的每个用例重新编译脚本。
,请记住,正如已经提到的val,在群集上可能非常沉重。您应该通过在function_score query
中添加过滤器(在我的示例中(添加过滤器来缩小设置文档的应用。无论如何,这不是应该使用Elasticsearch的方式,并且您不能期望使用这种黑客查询的表现出色。
1-滤波器文档,其中员工数组的大小为== 3
对于第一个问题,最好的办法是添加另一个根级字段(例如NbEmployees
(,该字段包含Employee
数组中的项目数,以便您可以使用range
查询而不是昂贵的script
查询。
然后,每当您修改Employee
数组时,您也可以相应地更新该NbEmployees
字段。效率要高得多!
2-滤波器文档,其中数组的第一个元素具有"名称" ==" John"
关于这一点,您需要知道嵌套字段是Lucene中的单独(隐藏(文档,因此无法在同一查询中立即访问所有嵌套的文档。
如果您知道您需要在查询中检查第一个员工的姓名,只需添加另一个根级字段FirstEmployeeName
并在该问题上运行查询。