如何更新 Elasticsearch/AWS Opensearch 中的嵌套数字字段值?

How to update nested numeric field value in Elasticsearch/ AWS Opensearch?

我对ES不是很熟悉,所以可能是我犯了一些错误。

我有一个具有以下映射的索引 users

{
   "mappings":{
      "dynamic":false,
      "properties":{
         "id":{
            "type":"keyword"
         },
         "userId":{
            "type":"text"
         },
         "total":{
            "type":"float"
         },
         "count":{
            "type":"float"
         },
         "earnings":{
            "properties":{
               "potential":{
                  "properties":{
                     "pending":{
                        "type":"float"
                     },
                     "finished":{
                        "type":"float"
                     }
                  }
               },
               "completed":{
                  "properties":{
                     "pending":{
                        "type":"float"
                     },
                     "paid":{
                        "type":"float"
                     }
                  }
               }
            }
         }
      }
   }
}

我想使用更新 API 更新 earnings.potential.pending 等嵌套字段。我有一个类似于下面使用 Update API.

的脚本
{
  "script" : {
    "source": "ctx._source.earnings.potential.pending += params.total",
    "lang": "painless",
    "params" : {
      "total" : 4
    }
  }
}


但是,我遇到了 illegal_argument_exception,点符号是下面假设的问题。

"ctx._source.earnings.potential.pending += params.total",
            ^---- HERE'

如果您尝试更新的文档中的 earnings 为空,您将收到错误消息:

...
"caused_by": {
  "type": "null_pointer_exception",
  "reason": "cannot access method/field [potential] from a null def reference"
}

所以本质上你需要在字段上设置一个默认值,如果它是空的话。最简单的方法是在编制索引时执行此操作,或者 运行 一次性查询以在所有位置设置默认值。但如果这不是一个选项,您可以扩展脚本以检查并分配默认值:

{
    "script": {
        "lang": "painless",
        "source": "if(ctx._source.earnings == null) { ctx._source.earnings = [:] }\n if(ctx._source.earnings.potential == null) { ctx._source.earnings.potential = [:] }\n if(ctx._source.earnings.potential.pending == null) { ctx._source.earnings.potential.pending = 0 } \n ctx._source.earnings.potential.pending += params.total",
        "params": {
            "total": 5
        }
    }
}