Set Field Value in Painless Script by Field Name as String

TL;DR

I'm trying to pass in a nested key to a Painless script as a string and set that key from the script, but it's not working. How do I do this?# Use Case

Long Version

Use Case

As a user, I need to perform the same transform in an ingest pipeline using a Painless script on multiple nested fields. However, the field name is arbitrary and will vary, based on the input data.

Current Solution

The best solution appears to be to pass the name of the nested field into the script as a string (e.g., a.b.c), but this does not work in all situations.

Example

Assume the following document structure:

{
    "a": {
        "b": {
            "c": "string"
        }
    }
}

Applying the following script to retrieve the value of a.b.c works as expected with the parameter { "source_field": "a.b.c" }:

def val = ctx;
def keys = params['source_field'].splitOnToken('.');
for (key in keys) {
    val = val[key];
}

val;

I don't like having to iterate down through the object to get the value for a.b.c, but it works.

If I execute the following code with the parameters { "source_field": "a.b.c", "dest_field": "d.e.f" }:

def val = ctx;
def keys = params['source_field'].splitOnToken('.');
for (key in keys) {
    val = val[key];
}

ctx[params['dest_field']] = val;

I get the expected output:

{
    "a": {
        "b": {
            "c": "string"
        }
    },
    "d": {
        "e": {
            "f": "string"
        }
    }
}

However, if d.e.f already exists and I'm attempting to overwrite the field, or even d exists, it does not save d.e.f to the document. Presumably this is because what I'm actually doing is creating a new key called {"d.e.f":"string"}.

How can I accomplish this?

Note: It would be great if the set ingest processor were exposed through the Processors object, but alas, it's not.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.