bru*_*upm 2 groovy elasticsearch
给定以下索引,如何在嵌套数组中选择适当的项并访问其中一个值?这里的目的是在里面的值里面使用它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
}
]
}
'
Run Code Online (Sandbox Code Playgroud)
我的查询按技巧_id过滤,效果很好.然后,我希望能够使用更高的给定skill_idscript_score来提高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)"
}
}
]
}
}
}
}
'
Run Code Online (Sandbox Code Playgroud)
如何访问skills从阵内script,找到"skill_id也:100"数组中的项目,然后用它的recommendations_count价值呢?在script_score上述目前不工作(比分始终是0,而不管数据的,所以我想doc['skills.recommendations_count'].value在正确的地方是不看.
对于您的特定问题,脚本需要嵌套上下文,就像您对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)"
}
}
]
}
}
}
}
}
}
}'
Run Code Online (Sandbox Code Playgroud)
对于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)"
}
}
]
}
}
}
}
}
}
}'
Run Code Online (Sandbox Code Playgroud)
注意:我将term查询设置为term过滤器,因为它对分数没有逻辑影响(它或者是完全匹配).我还将嵌套字段的名称添加到term过滤器中,这是Elasticsearch 2.x及更高版本(以及之前的良好实践)中的一项要求.
除此之外,您可以(并且应该)尽可能避免使用脚本.这是其中一个案例.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
}
}
]
}
}
}
}
}
}
}'
Run Code Online (Sandbox Code Playgroud)
对于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
}
}
]
}
}
}
}
}
}
}'
Run Code Online (Sandbox Code Playgroud)
脚本很慢,它们也暗示在Elasticsearch 1.x中使用fielddata,这很糟糕.你确实提到了doc值,这是一个有希望的开始,表明使用Elasticsearch 2.x,但这可能只是术语.
如果您刚刚开始使用Elasticsearch,那么我强烈建议您从最新版本开始.