ElasticSearch null_pointer_exception当尝试使用ctx._source访问任何对象类型的字段时

qv7cva1a  于 2023-10-17  发布在  ElasticSearch
关注(0)|答案(2)|浏览(104)

我有一个如下的索引Map

PUT /customer-index
{
  "mappings":{
    "properties":{
        "customers.id": {
        "type": "long"
      },
      "customers.name": {
        "type": "text",
        "norms": false
      },
      "customers.company": {
        "type": "text",
        "norms": false
      }
    }
  }
}

在这个索引中,我添加了两个文件

PUT /customer-index/_doc/1
{
  "customers.company" : "google",
  "customers.id" : 1,
  "customers.name" : "adams"
}

PUT /customer-index/_doc/2
{
  "customers.company" : "apple",
  "customers.id" : 2,
  "customers.name" : "james"
}

现在我试图使用update by query更新公司到三星的id是2。在真实的场景中,我必须更新多个索引中id匹配的多个文档,这就是我使用update by query的原因。但为了简单起见,我这样张贴

POST /customer-index/_update_by_query
{
  "script": {
    "source": "ctx._source.customers.company = params.company",
    "lang": "painless",
    "params": {
      "company": "samsung"
    }
  },
  "query": {
    "term": {
      "customers.id": 2
    }
  }
}

但它总是抛出null_pointer_exception

{
  "error": {
    "root_cause": [
      {
        "type": "script_exception",
        "reason": "runtime error",
        "script_stack": [
          "ctx._source.customers.company = params.company",
          "                     ^---- HERE"
        ],
        "script": "ctx._source.customers.company = params.company",
        "lang": "painless",
        "position": {
          "offset": 21,
          "start": 0,
          "end": 46
        }
      }
    ],
    "type": "script_exception",
    "reason": "runtime error",
    "script_stack": [
      "ctx._source.customers.company = params.company",
      "                     ^---- HERE"
    ],
    "script": "ctx._source.customers.company = params.company",
    "lang": "painless",
    "position": {
      "offset": 21,
      "start": 0,
      "end": 46
    },
    "caused_by": {
      "type": "null_pointer_exception",
      "reason": "Cannot invoke \"Object.getClass()\" because \"callArgs[0]\" is null"
    }
  },
  "status": 400
}

添加一个null检查可以避免这个错误,但我的问题是,为什么我得到null_pointer_exception时,我有索引中的文档。我已经检查了很多地方,但仍然没有运气。请帮帮我

kgqe7b3p

kgqe7b3p1#

由于customers不是一个对象类型,因此需要像这样访问它:

ctx._source['customers.company']

如果你像这样声明customers字段,你的查询就可以工作:

PUT /customer-index
{
  "mappings":{
    "properties":{
      "customers": {
        "type": "object",
        "properties": {
          "id": {
            "type": "long"
          },
          "customers.name": {
            "type": "text",
            "norms": false
          },
          "customers.company": {
            "type": "text",
            "norms": false
          }
        }
      }
    }
  }
}
zmeyuzjn

zmeyuzjn2#

我挖得更深一点,发现了下面的东西。我将试着用一个例子来解释它。我们创建两个索引,customer-index-10customer-index-20

PUT /customer-index-10
{
  "mappings": {
    "properties": {
      "customers": {
        "type": "object",
        "properties": {
          "id": {
            "type": "long"
          },
          "name": {
            "type": "text",
            "norms": false
          },
          "company": {
            "type": "text",
            "norms": false
          }
        }
      }
    }
  }
}
PUT /customer-index-20
{
  "mappings": {
    "properties": {
      "customers.id": {
        "type": "long"
      },
      "customers.name": {
        "type": "text",
        "norms": false
      },
      "customers.company": {
        "type": "text",
        "norms": false
      }
    }
  }
}

如果在两个索引上调用_mapping API,它将返回相同的结果,这意味着在两种情况下,客户都将被视为类型对象。但是查询更新在两个索引中的工作方式是不同的。
对于索引/customer-index-10,这样的脚本将工作
"source" : "ctx._source.customers.name = 'updated name'"
但是对于索引/customer-index-20,上面的脚本将抛出指针异常,下面的脚本将工作
"source" : "ctx._source['customers.name'] = 'updated name'"

相关问题