如何基于Elasticsearch中的先前值更新具有不同值的字段?

时间:2019-06-25 12:43:50

标签: elasticsearch

我想根据一个字段的先前值来更新一个新值。例如:如果字段“设置”值是“ aaa”或“ bbb”,我想提供一个新值列表,例如,“ aaa”变成“ ccc”,“ bbb”变成“ ddd”。

此查询是我被卡住的

POST my_index/_update_by_query?conflicts=proceed
{
  "query": {
    "terms": {"set.keyword": ["aaa", "bbb"]}
  },
  "script": {
    "inline": "ctx._source.set = 'ccc'; ctx._source.set = 'ddd';"
  }
}

所有值都更新为“ ddd”,而不是获得不同的更新值(“ ccc”或“ ddd”,具体取决于先前的值)。我怀疑它两次更新所有值。

  • 使用下面的Val查询,我得到以下输出:
{
  "error": {
    "root_cause": [
      {
        "type": "script_exception",
        "reason": "runtime error",
        "script_stack": [
          "ctx._source.set = ctx._source.set.stream().map(elem -> {\n         ",
          "                                 ^---- HERE"
        ],
        "script": "       ctx._source.set = ctx._source.set.stream().map(elem -> {\n         if (params[elem] != null) {\n           return params[elem];\n         } else {\n           return elem;\n         }\n       }).collect(Collectors.toList());",
        "lang": "painless"
      }
    ],
    "type": "script_exception",
    "reason": "runtime error",
    "script_stack": [
      "ctx._source.set = ctx._source.set.stream().map(elem -> {\n         ",
      "                                 ^---- HERE"
    ],
    "script": "       ctx._source.set = ctx._source.set.stream().map(elem -> {\n         if (params[elem] != null) {\n           return params[elem];\n         } else {\n           return elem;\n         }\n       }).collect(Collectors.toList());",
    "lang": "painless",
    "caused_by": {
      "type": "illegal_argument_exception",
      "reason": "Unable to find dynamic method [stream] with [0] arguments for class [java.lang.String]."
    }
  },
  "status": 500
}
  • 映射未明确提及“设置”字段:

    MY_MAPPING = '''{
                    "mappings": {
                        "data_type": {
                            "properties": {
                                "delivered": {
                                    "type": "date",
                                    "format": "yyyy-MM-dd"
                                },
                                "requested": {
                                    "type": "date",
                                    "format": "yyyy-MM-dd"
                                },
                                "location": {
                                    "type": "geo_point"
                                }                            

                            }
                        }
                    }
                }'''

看看索引,我将“ set”设置为可搜索的字符串,并将“ set.keyword”设置为可搜索和可聚合的字符串。

1 个答案:

答案 0 :(得分:0)

我会这样:

POST my_index/_update_by_query?conflicts=proceed
{
  "query": {
    "terms": {"set.keyword": ["aaa", "bbb"]}
  },
  "script": {
    "source": """
       def currentSet = ctx._source.set;
       ctx._source.set = (params[currentSet] != null) ? params[currentSet] : currentSet;
    """,
    "params": {
      "aaa": "ccc",
      "bbb": "ddd"
    }
  }
}

换句话说,脚本将迭代set数组,对于每个元素,它将为给定的旧值返回params哈希中的新值,如果没有新值,则返回旧值本身值。

如果您的set["aaa", "bbb", "xxx"],则在更新索引后,该索引将包含["ccc", "ddd", "xxx"]