给定以下索引,我如何在嵌套数组中选择适当的项目并访问其中的一个值?目的是在内的值中使用它script_score。
script_score
# Create mapping curl -XPUT localhost:9200/test/user/_mapping -d ' { "user" : { "properties" : { "name" : { "type" : "string" }, "skills" : { "type": "nested", "properties" : { "skill_id" : { "type" : "integer" }, "recommendations_count" : { "type" : "integer" } } } } } } ' # Indexing Data curl -XPUT localhost:9200/test/user/1 -d ' { "name": "John", "skills": [ { "skill_id": 100, "recommendations_count": 5 }, { "skill_id": 200, "recommendations_count": 3 } ] } ' curl -XPUT localhost:9200/test/user/2 -d ' { "name": "Mary", "skills": [ { "skill_id": 100, "recommendations_count": 9 }, { "skill_id": 200, "recommendations_count": 0 } ] } '
我的查询按skill_id过滤,效果很好。然后,我希望能够 针对给定的skill_id 使用更高script_score的分数来提高user文档的分数recommendations_count 。 (<-这是关键)。
user
recommendations_count
curl -XPOST localhost:9200/test/user/_search -d ' { "query":{ "function_score":{ "query":{ "bool":{ "must":{ "nested":{ "path":"skills", "query":{ "bool":{ "must":{ "term":{ "skill_id":100 } } } } } } } }, "functions":[ { "script_score": { "script": "sqrt(1.2 * doc['skills.recommendations_count'].value)" } } ] } } } } '
如何skills从中访问数组,在数组中script找到’skill_id:100’项目,然后使用其recommendations_count值?在script_score上述目前不工作(比分始终是0,而不管数据的,所以我想doc['skills.recommendations_count'].value在正确的地方是不看。
skills
script
doc['skills.recommendations_count'].value
对于您的特定问题,脚本需要嵌套上下文,就像您对term查询所做的一样。
term
可以为ES 1.x重写:
curl -XGET 'localhost:9200/test/_search' -d' { "query": { "nested": { "path": "skills", "query": { "filtered": { "filter": { "term": { "skills.skill_id": 100 } }, "query": { "function_score": { "functions": [ { "script_score": { "script": "sqrt(1.2 * doc['skills.recommendations_count'].value)" } } ] } } } } } } }'
对于ES 2.x(过滤器在ES 2.x中成为一等公民,因此语法进行了一些更改以跟上!):
curl -XGET 'localhost:9200/test/_search' -d' { "query": { "nested": { "path": "skills", "query": { "bool": { "filter": { "term": { "skills.skill_id": 100 } }, "must": { "function_score": { "functions": [ { "script_score": { "script": "sqrt(1.2 * doc['skills.recommendations_count'].value)" } } ] } } } } } } }'
注意:我使term查询成为term过滤器,因为它对分数没有逻辑影响(无论是完全匹配还是不完全匹配)。我还将嵌套字段的名称添加到了term过滤器中,这是Elasticsearch 2.x和更高版本(以及先前的良好实践)的要求。
这样一来,您就可以( 并且 应该)避免尽可能使用脚本。这是其中一种情况。function_score支持field_value_factor功能的概念,该功能使您可以完全按照自己的尝试去做,但完全不需要脚本。您还可以选择提供一个“ missing”值来控制如果缺少该字段会发生什么。
function_score
field_value_factor
这将转换为 完全相同 的脚本,但是会表现得更好:
curl -XGET 'localhost:9200/test/_search' -d' { "query": { "nested": { "path": "skills", "query": { "filtered": { "filter": { "term": { "skills.skill_id": 100 } }, "query": { "function_score": { "functions": [ { "field_value_factor": { "field": "skills.recommendations_count", "factor": 1.2, "modifier": "sqrt", "missing": 0 } } ] } } } } } } }'
对于ES 2.x:
curl -XGET 'localhost:9200/test/_search' -d' { "query": { "nested": { "path": "skills", "query": { "bool": { "filter": { "term": { "skills.skill_id": 100 } }, "must": { "function_score": { "functions": [ { "field_value_factor": { "field": "skills.recommendations_count", "factor": 1.2, "modifier": "sqrt", "missing": 0 } } ] } } } } } } }'
脚本很慢,并且 也 暗示着Elasticsearch 1.x中使用fielddata,这很糟糕。您确实提到了doc值,这是一个有希望的开端,它表明使用Elasticsearch 2.x,但这可能只是术语。
如果您只是从Elasticsearch开始,那么我强烈建议从最新版本开始。