【问题标题】:ElasticSearch, simple two fields comparison with painlessElasticSearch,简单的两个字段比较与painless
【发布时间】:2021-01-22 21:08:13
【问题描述】:

我正在尝试运行 SELECT * FROM indexPeople WHERE info.Age > info.AgeExpectancy 之类的查询

注意这两个字段没有嵌套,它们只是 json 对象

POST /indexPeople/_search
{
  "from" : 0,
  "size" : 200,
  "query" : {
    "bool" : {
      "filter" : [
        {
          "bool" : {
            "must" : [
              {
                "script" : {
                  "script" : {
                    "source" : "doc['info.Age'].value > doc['info.AgeExpectancy'].value",
                    "lang" : "painless"
                  },
                  "boost" : 1.0
                }
              }
            ],
            "adjust_pure_negative" : true,
            "boost" : 1.0
          }
        }
      ],
      "adjust_pure_negative" : true,
      "boost" : 1.0
    }
  },
  "_source" : {
    "includes" : [
      "info"
    ],
    "excludes" : [ ]
  }
}

但是这个查询失败了

{
  "error" : {
    "root_cause" : [
      {
        "type" : "script_exception",
        "reason" : "runtime error",
        "script_stack" : [
          "org.elasticsearch.index.fielddata.ScriptDocValues$Longs.get(ScriptDocValues.java:121)",
          "org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValue(ScriptDocValues.java:115)",
          "doc['info.Age'].value > doc['info.AgeExpectancy'].value",
          "               ^---- HERE"
        ],
        "script" : "doc['info.Age'].value > doc['info.AgeExpectancy'].value",
        "lang" : "painless",
        "position" : {
          "offset" : 22,
          "start" : 0,
          "end" : 70
        }
      }
    ],
    "type" : "search_phase_execution_exception",
    "reason" : "all shards failed",
    "phase" : "query",
    "grouped" : true,
    "failed_shards" : [
      {
        "shard" : 0,
        "index" : "indexPeople",
        "node" : "c_Dv3IrlQmyvIVpLoR9qVA",
        "reason" : {
          "type" : "script_exception",
          "reason" : "runtime error",
          "script_stack" : [
            "org.elasticsearch.index.fielddata.ScriptDocValues$Longs.get(ScriptDocValues.java:121)",
            "org.elasticsearch.index.fielddata.ScriptDocValues$Longs.getValue(ScriptDocValues.java:115)",
            "doc['info.Age'].value > doc['info.AgeExpectancy'].value",
            "               ^---- HERE"
          ],
          "script" : "doc['info.Age'].value > doc['info.AgeExpectancy'].value",
          "lang" : "painless",
          "position" : {
            "offset" : 22,
            "start" : 0,
            "end" : 70
          },
          "caused_by" : {
            "type" : "illegal_state_exception",
            "reason" : "A document doesn't have a value for a field! Use doc[<field>].size()==0 to check if a document is missing a field!"
          }
        }
      }
    ]
  },
  "status" : 400
}

有没有办法做到这一点? 调试它的最佳方法是什么?我想打印对象或查看日志(不存在),但我都找不到这样做的方法。

映射为:

{
  "mappings": {
    "_doc": {
      "properties": {
        "info": {
          "properties": {
            "Age": {
              "type": "long"
            },
            "AgeExpectancy": {
              "type": "long"
            }
          }
        }
      }
    }
  }
}

【问题讨论】:

    标签: elasticsearch elasticsearch-painless


    【解决方案1】:

    也许你已经解决了这个问题。查询失败的原因很清楚:

    "caused_by" : {
                "type" : "illegal_state_exception",
                "reason" : "A document doesn't have a value for a field! Use doc[<field>].size()==0 to check if a document is missing a field!"
    }
    

    基本上有一个或多个文档没有一个的查询字段。因此,您可以通过使用 if 检查字段是否确实存在来获得所需的结果。如果它们不存在,您可以简单地返回 false,如下所示:

    {
      "script": """
        if (doc['info.Age'].size() > 0 && doc['info.AgeExpectancy'].size() > 0) {
          return doc['info.Age'].value > doc['info.AgeExpectancy'].value
        }
        return false;
    }
    """
    

    我用 Elasticsearch 7.10.2 对其进行了测试,它可以工作。

    调试它的最佳方法是什么

    这是一个问题,也许有人对此有更好的答案。我尝试列出一些选项。显然,调试需要仔细阅读错误信息。

    无痛实验室 如果您有最新版本的 Kibana,您可以尝试使用无痛实验室来模拟您的文档,并在更集中的环境中更快地发现错误。

    KIBANA 脚本字段 您可以尝试在名为条件的索引模式中创建一个布尔脚本字段。在点击创建之前记得点击“预览结果”:

    最小示例创建一个最小示例以降低复杂性。 对于这个答案,我使用了包含所有可能情况的四个文档的示例索引。

    1. 没有信息:{ "message": "ok"}
    2. Info.Age 但不是 AgeExpectancy:{"message":"ok","info":{"Age":14}}
    3. Info.AgeExpectancy 但不是年龄:{"message":"ok","info":{"AgeExpectancy":12}}
    4. Info.Age 和 AgeExpectancy:{"message":"ok","info":{"Age":14, "AgeExpectancy": 12}}

    【讨论】:

      猜你喜欢
      • 2018-12-03
      • 1970-01-01
      • 2021-12-04
      • 2021-12-11
      • 2015-02-26
      • 1970-01-01
      • 1970-01-01
      • 2013-01-12
      • 2011-10-30
      相关资源
      最近更新 更多