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

时间:2015-12-23 07:57:22

标签: elasticsearch groovy

鉴于以下索引,如何在嵌套数组中选择适当的项并访问其中一个值?这里的目的是在system内的值中使用它。

script_score

我的查询按技巧_id过滤,效果很好。然后,我希望能够使用# 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 } ] } ' 来提高script_score个文档的分数,并为给定的skill_id提高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数组,找到' skill_id:100'数组中的项,然后使用其script值?上面的recommendations_count目前无效(无论数据如何,得分始终为0,因此我认为script_score没有找到正确的位置。

1 个答案:

答案 0 :(得分:6)

对于您的特定问题,脚本需要嵌套上下文,就像您使用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 supports the concept of a field_value_factor function that lets you do things exactly like you are trying, but entirely without a script。您还可以选择提供“缺失”值,以控制在缺少字段时发生的情况。

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

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
                  }
                }
              ]
            }
          }
        }
      }
    }
  }
}'

脚本很慢且they also imply the use of fielddata in Elasticsearch 1.x, which is bad。你确实提到了doc值,这是一个很有希望的开始,表明使用Elasticsearch 2.x,但这可能只是术语。

如果您刚开始使用Elasticsearch,我强烈建议您从最新版本开始。