elasticsearch - 在script_score中使用嵌套值

标签 elasticsearch lucene kibana elasticsearch-painless

我正在尝试在脚本分数中使用嵌套值,但是在使它起作用时遇到了问题,因为我无法通过 doc 访问该字段来遍历该字段。另外,当我尝试像_type:images AND _exists_:colors这样在Kibana中查询它时,它将不匹配任何文档,即使当我逐个查看它们时,所有文档中都清楚地显示了该字段。但是,我可以使用 params._source 来访问它,但是我已经读到它可能会变慢,因此不建议这样做。

我知道这个问题完全是由我们创建此嵌套字段的方式造成的,因此,如果我无法提出比这更好的东西,则必须重新索引2m +文档,看看是否可以找到解决该问题的另一种方法,但是我想避免这种情况,并且还可以更好地了解Elastic在幕后的工作方式以及它在这里的工作方式。

我将在此处提供的示例不是我的现实生活中的问题,而是也描述了该问题。
假设我们有一个描述图像的文档。该文档的字段包含图像中红色,蓝色和绿色的数量。

请求创建带有嵌套字段的索引和文档,该嵌套字段包含颜色数组,它们之间分为100点:

PUT images
{
  "settings": {
    "number_of_shards": 1
  },
  "mappings": {
    "_doc": {
      "properties": {
        "id" : { "type" : "integer" },
        "title" : { "type" : "text" },
        "description" : { "type" : "text" },
        "colors": {
          "type": "nested",
          "properties": {
            "red": {
              "type": "double"
            },
            "green": {
              "type": "double"
            },
            "blue": {
              "type": "double"
            }
          }
        }
      }
    }
  }
}

PUT images/_doc/1
{
    "id" : 1,
    "title" : "Red Image",
    "description" : "Description of Red Image",
    "colors": [
      {
        "red": 100
      },
      {
        "green": 0
      },
      {
        "blue": 0
      }
    ]
}

PUT images/_doc/2
{
    "id" : 2,
    "title" : "Green Image",
    "description" : "Description of Green Image",
    "colors": [
      {
        "red": 0
      },
      {
        "green": 100
      },
      {
        "blue": 0
      }
    ]
}

PUT images/_doc/3
{
    "id" : 3,
    "title" : "Blue Image",
    "description" : "Description of Blue Image",
    "colors": [
      {
        "red": 0
      },
      {
        "green": 0
      },
      {
        "blue": 100
      }
    ]
}

现在,如果我运行此查询,请使用 doc :
GET images/_search
{
  "query": {
    "function_score": {
      "functions": [
        {
          "script_score": {
            "script": {
              "source": """
                boolean debug = true;
                for(color in doc["colors"]) {
                  if (debug === true) {
                    throw new Exception(color["red"].toString());
                  }
                }
              """
            }
          }
        }
      ]
    }
  }
}

我将获得No field found for [colors] in mapping with types []异常,但如果我使用 params._source 代替,则如下所示:
GET images/_search
{
  "query": {
    "function_score": {
      "functions": [
        {
          "script_score": {
            "script": {
              "source": """
                boolean debug = true;
                for(color in params._source["colors"]) {
                  if (debug === true) {
                    throw new Exception(color["red"].toString());
                  }
                }
              """
            }
          }
        }
      ]
    }
  }
}

我能够输出"caused_by": {"type": "exception", "reason": "100"},所以我知道它工作了,因为第一个文档是红色的,并且值为100。

我什至不确定这是否可以归类为问题,但更需要帮助。如果有人可以解释这种现象的发生原因,并给出解决该问题的最佳方法的想法,我将不胜感激。

(此外,在Painless中调试的一些技巧也很可爱!!)

最佳答案

不用担心params._source的速度慢-这是您唯一的选择,因为迭代doc的嵌套上下文仅允许访问一种嵌套颜色。

试试这个:

GET images/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": "image"
          }
        },
        {
          "function_score": {
            "functions": [
              {
                "script_score": {
                  "script": {
                    "source": """
                        def score = 0;
                        for (color in params._source["colors"]) {
                          // Debug.explain(color);
                          if (color.containsKey('red')) {
                            score += color['red'] ;
                          }
                        }
                        return score;
                    """
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

无痛评分上下文是here

其次,您非常接近手动抛出异常-不过,有一种更干净的方法可以执行此操作。取消注释Debug.explain(color);,就可以了。

另外,我故意添加了match查询来提高得分,但更重要的是,它说明了后台如何构建查询-当您在GET images/_validate/query?explain下重新运行上述内容时,您会自己看到。

关于elasticsearch - 在script_score中使用嵌套值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61238594/

相关文章:

java - apache lucene 在文件路径上索引和搜索

regex - Kibana 中的正则表达式问题

java - Solr中添加自定义查询参数的正确方法

elasticsearch - 如何在 Kibana 中进行时间范围搜索

elasticsearch - 混合嵌套查询和脚本过滤器

json - 在 Logstash 中,如何限制在 Elasticsearch 中转换为索引字段的日志中 JSON 属性的深度?

elasticsearch - 在CoreOS(使用Docker)上运行elasticsearch相对于Ubuntu有什么优势

elasticsearch - 如何根据另一个索引/类型的聚合进行排序

apache-spark - saveJsonToEs 需要太多时间来处理每个元素,即使节点没有重载

java - lucene中精确度和召回率测量的问题