当前位置:  开发笔记 > 数据库 > 正文

如何在Elasticsearch脚本中访问嵌套数组的doc值?

如何解决《如何在Elasticsearch脚本中访问嵌套数组的doc值?》经验,为你挑选了1个好方法。

给定以下索引,如何在嵌套数组中选择适当的项并访问其中一个值?这里的目的是在里面的值里面使用它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
      }
   ]
}
'

我的查询按技巧_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)"   
            }
          }            
        ]
      }
    }
  }
} 
'

如何访问skills从阵内script,找到"skill_id也:100"数组中的项目,然后用它的recommendations_count价值呢?在script_score上述目前不工作(比分始终是0,而不管数据的,所以我想doc['skills.recommendations_count'].value在正确的地方是不看.



1> pickypg..:

对于您的特定问题,脚本需要嵌套上下文,就像您对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函数的概念,它允许您完成与您尝试的完全相同的事情,但完全没有脚本.您还可以选择提供"缺失"值,以控制在缺少字段时发生的情况.

这转换为完全相同的脚本,但它会表现得更好:

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,那么我强烈建议您从最新版本开始.

推荐阅读
135369一生真爱_890
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有