我试图弄清楚如何解决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-过滤文档,其中数组的第一个元素具有“名称” ==“约翰”
我试图迈出一些第一步,但是我无法遍历列表。我总是有一个空指针异常错误。
{
"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
}
"""
}
}
]
}
}
}
}
}
}
答案 0 :(得分:1)
1-过滤员工数组大小== 3的文档
对于第一个问题,最好的办法是添加另一个包含NbEmployees
数组中项数的根级字段(例如Employee
),以便您可以使用{ {1}}查询,而不是昂贵的range
查询。
然后,每当您修改script
数组时,也将相应地更新Employee
字段。更有效率!
2-过滤文档,其中数组的第一个元素具有“名称” ==“约翰”
关于这一点,您需要知道嵌套字段是Lucene中单独的(隐藏)文档,因此无法在同一查询中一次访问所有嵌套文档。
如果您知道需要在查询中检查第一位员工的姓名,只需添加另一个根级别字段NbEmployees
并在该字段上运行查询即可。
答案 1 :(得分:1)
Val注意到,您无法在Elasticsearch的最新版本中的脚本查询中访问_source
个文档。
但是elasticsearch允许您在“得分上下文”中访问此_source
。
因此,一种可能的解决方法(但您需要注意性能)是在查询中结合使用脚本分数和min_score。
您可以在此堆栈溢出帖子Query documents by sum of nested field values in elasticsearch中找到此行为的示例。
在您的情况下,像这样的查询可以完成这项工作:
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"
}
}
}
}
]
}
}
}
应在参数中设置Employee的名称和名字,以避免针对此脚本的每个用例重新编写脚本。
但是请记住,如Val所述,它在您的集群上可能非常繁重。您应该通过在function_score query
(在我的示例中为match_all)中添加过滤器来缩小文档的适用范围。
而且无论如何,这都不是应使用Elasticsearch的方式,并且您无法期望通过这种被黑的查询获得出色的性能。