| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954 | [[pipeline]]== Pipeline DefinitionA pipeline is a definition of  a series of <<ingest-processors, processors>> that are to be executedin the same order as they are declared. A pipeline consists of two main fields: a `description`and a list of `processors`:[source,js]--------------------------------------------------{  "description" : "...",  "processors" : [ ... ]}--------------------------------------------------The `description` is a special field to store a helpful description ofwhat the pipeline does.The `processors` parameter defines a list of processors to be executed inorder.[[ingest-apis]]== Ingest APIsThe following ingest APIs are available for managing pipelines:* <<put-pipeline-api>> to add or update a pipeline* <<get-pipeline-api>> to return a specific pipeline* <<delete-pipeline-api>> to delete a pipeline* <<simulate-pipeline-api>> to simulate a call to a pipeline[[put-pipeline-api]]=== Put Pipeline APIThe put pipeline API adds pipelines and updates existing pipelines in the cluster.[source,js]--------------------------------------------------PUT _ingest/pipeline/my-pipeline-id{  "description" : "describe pipeline",  "processors" : [    {      "set" : {        "field": "foo",        "value": "bar"      }    }  ]}--------------------------------------------------// CONSOLENOTE: The put pipeline API also instructs all ingest nodes to reload their in-memory representation of pipelines, so that      pipeline changes take effect immediately.[[get-pipeline-api]]=== Get Pipeline APIThe get pipeline API returns pipelines based on ID. This API always returns a local reference of the pipeline.[source,js]--------------------------------------------------GET _ingest/pipeline/my-pipeline-id--------------------------------------------------// CONSOLE// TEST[continued]Example response:[source,js]--------------------------------------------------{  "my-pipeline-id" : {    "description" : "describe pipeline",    "processors" : [      {        "set" : {          "field" : "foo",          "value" : "bar"        }      }    ]  }}--------------------------------------------------// TESTRESPONSEFor each returned pipeline, the source and the version are returned.The version is useful for knowing which version of the pipeline the node has.You can specify multiple IDs to return more than one pipeline. Wildcards are also supported.[float][[versioning-pipelines]]==== Pipeline VersioningPipelines can optionally add a `version` number, which can be any integer value,in order to simplify pipeline management by external systems. The `version`field is completely optional and it is meant solely for external management ofpipelines. To unset a `version`, simply replace the pipeline without specifyingone.[source,js]--------------------------------------------------PUT _ingest/pipeline/my-pipeline-id{  "description" : "describe pipeline",  "version" : 123,  "processors" : [    {      "set" : {        "field": "foo",        "value": "bar"      }    }  ]}--------------------------------------------------// CONSOLETo check for the `version`, you can<<common-options-response-filtering, filter responses>>using `filter_path` to limit the response to just the `version`:[source,js]--------------------------------------------------GET /_ingest/pipeline/my-pipeline-id?filter_path=*.version--------------------------------------------------// TEST[continued]This should give a small response that makes it both easy and inexpensive to parse:[source,js]--------------------------------------------------{  "my-pipeline-id" : {    "version" : 123  }}--------------------------------------------------// TESTRESPONSE[[delete-pipeline-api]]=== Delete Pipeline APIThe delete pipeline API deletes pipelines by ID or wildcard match (`my-*`, `*`).[source,js]--------------------------------------------------DELETE _ingest/pipeline/my-pipeline-id--------------------------------------------------// CONSOLE// TEST[continued]////Hidden setup for wildcard test:[source,js]--------------------------------------------------PUT _ingest/pipeline/wild-one{  "description" : "first pipeline to be wildcard deleted",  "processors" : [ ]}PUT _ingest/pipeline/wild-two{  "description" : "second pipeline to be wildcard deleted",  "processors" : [ ]}DELETE _ingest/pipeline/*--------------------------------------------------// CONSOLEHidden expected response:[source,js]--------------------------------------------------{"acknowledged": true}--------------------------------------------------// TESTRESPONSE////[[simulate-pipeline-api]]=== Simulate Pipeline APIThe simulate pipeline API executes a specific pipeline againstthe set of documents provided in the body of the request.You can either specify an existing pipeline to executeagainst the provided documents, or supply a pipeline definition inthe body of the request.Here is the structure of a simulate request with a pipeline definition providedin the body of the request:[source,js]--------------------------------------------------POST _ingest/pipeline/_simulate{  "pipeline" : {    // pipeline definition here  },  "docs" : [    { /** first document **/ },    { /** second document **/ },    // ...  ]}--------------------------------------------------Here is the structure of a simulate request against an existing pipeline:[source,js]--------------------------------------------------POST _ingest/pipeline/my-pipeline-id/_simulate{  "docs" : [    { /** first document **/ },    { /** second document **/ },    // ...  ]}--------------------------------------------------Here is an example of a simulate request with a pipeline defined in the requestand its response:[source,js]--------------------------------------------------POST _ingest/pipeline/_simulate{  "pipeline" :  {    "description": "_description",    "processors": [      {        "set" : {          "field" : "field2",          "value" : "_value"        }      }    ]  },  "docs": [    {      "_index": "index",      "_type": "type",      "_id": "id",      "_source": {        "foo": "bar"      }    },    {      "_index": "index",      "_type": "type",      "_id": "id",      "_source": {        "foo": "rab"      }    }  ]}--------------------------------------------------// CONSOLEResponse:[source,js]--------------------------------------------------{   "docs": [      {         "doc": {            "_id": "id",            "_ttl": null,            "_parent": null,            "_index": "index",            "_routing": null,            "_type": "type",            "_timestamp": null,            "_source": {               "field2": "_value",               "foo": "bar"            },            "_ingest": {               "timestamp": "2016-01-04T23:53:27.186+0000"            }         }      },      {         "doc": {            "_id": "id",            "_ttl": null,            "_parent": null,            "_index": "index",            "_routing": null,            "_type": "type",            "_timestamp": null,            "_source": {               "field2": "_value",               "foo": "rab"            },            "_ingest": {               "timestamp": "2016-01-04T23:53:27.186+0000"            }         }      }   ]}--------------------------------------------------[[ingest-verbose-param]]==== Viewing Verbose ResultsYou can use the simulate pipeline API to see how each processor affects the ingest documentas it passes through the pipeline. To see the intermediate results ofeach processor in the simulate request, you can add the `verbose` parameterto the request.Here is an example of a verbose request and its response:[source,js]--------------------------------------------------POST _ingest/pipeline/_simulate?verbose{  "pipeline" :  {    "description": "_description",    "processors": [      {        "set" : {          "field" : "field2",          "value" : "_value2"        }      },      {        "set" : {          "field" : "field3",          "value" : "_value3"        }      }    ]  },  "docs": [    {      "_index": "index",      "_type": "type",      "_id": "id",      "_source": {        "foo": "bar"      }    },    {      "_index": "index",      "_type": "type",      "_id": "id",      "_source": {        "foo": "rab"      }    }  ]}--------------------------------------------------// CONSOLEResponse:[source,js]--------------------------------------------------{   "docs": [      {         "processor_results": [            {               "tag": "processor[set]-0",               "doc": {                  "_id": "id",                  "_ttl": null,                  "_parent": null,                  "_index": "index",                  "_routing": null,                  "_type": "type",                  "_timestamp": null,                  "_source": {                     "field2": "_value2",                     "foo": "bar"                  },                  "_ingest": {                     "timestamp": "2016-01-05T00:02:51.383+0000"                  }               }            },            {               "tag": "processor[set]-1",               "doc": {                  "_id": "id",                  "_ttl": null,                  "_parent": null,                  "_index": "index",                  "_routing": null,                  "_type": "type",                  "_timestamp": null,                  "_source": {                     "field3": "_value3",                     "field2": "_value2",                     "foo": "bar"                  },                  "_ingest": {                     "timestamp": "2016-01-05T00:02:51.383+0000"                  }               }            }         ]      },      {         "processor_results": [            {               "tag": "processor[set]-0",               "doc": {                  "_id": "id",                  "_ttl": null,                  "_parent": null,                  "_index": "index",                  "_routing": null,                  "_type": "type",                  "_timestamp": null,                  "_source": {                     "field2": "_value2",                     "foo": "rab"                  },                  "_ingest": {                     "timestamp": "2016-01-05T00:02:51.384+0000"                  }               }            },            {               "tag": "processor[set]-1",               "doc": {                  "_id": "id",                  "_ttl": null,                  "_parent": null,                  "_index": "index",                  "_routing": null,                  "_type": "type",                  "_timestamp": null,                  "_source": {                     "field3": "_value3",                     "field2": "_value2",                     "foo": "rab"                  },                  "_ingest": {                     "timestamp": "2016-01-05T00:02:51.384+0000"                  }               }            }         ]      }   ]}--------------------------------------------------[[accessing-data-in-pipelines]]== Accessing Data in PipelinesThe processors in a pipeline have read and write access to documents that pass through the pipeline.The processors can access fields in the source of a document and the document's metadata fields.[float][[accessing-source-fields]]=== Accessing Fields in the SourceAccessing a field in the source is straightforward. You simply refer to fields bytheir name. For example:[source,js]--------------------------------------------------{  "set": {    "field": "my_field"    "value": 582.1  }}--------------------------------------------------On top of this, fields from the source are always accessible via the `_source` prefix:[source,js]--------------------------------------------------{  "set": {    "field": "_source.my_field"    "value": 582.1  }}--------------------------------------------------[float][[accessing-metadata-fields]]=== Accessing Metadata FieldsYou can access metadata fields in the same way that you access fields in the source. Thisis possible because Elasticsearch doesn't allow fields in the source that have thesame name as metadata fields.The following example sets the `_id` metadata field of a document to `1`:[source,js]--------------------------------------------------{  "set": {    "field": "_id"    "value": "1"  }}--------------------------------------------------The following metadata fields are accessible by a processor: `_index`, `_type`, `_id`, `_routing`, `_parent`.[float][[accessing-ingest-metadata]]=== Accessing Ingest Metadata FieldsBeyond metadata fields and source fields, ingest also adds ingest metadata to the documents that it processes.These metadata properties are accessible under the `_ingest` key. Currently ingest adds the ingest timestampunder the `_ingest.timestamp` key of the ingest metadata. The ingest timestamp is the time when Elasticsearchreceived the index or bulk request to pre-process the document.Any processor can add ingest-related metadata during document processing. Ingest metadata is transientand is lost after a document has been processed by the pipeline. Therefore, ingest metadata won't be indexed.The following example adds a field with the name `received`. The value is the ingest timestamp:[source,js]--------------------------------------------------{  "set": {    "field": "received"    "value": "{{_ingest.timestamp}}"  }}--------------------------------------------------Unlike Elasticsearch metadata fields, the ingest metadata field name `_ingest` can be used as a valid field namein the source of a document. Use `_source._ingest` to refer to the field in the source document. Otherwise, `_ingest`will be interpreted as an ingest metadata field.[float][[accessing-template-fields]]=== Accessing Fields and Metafields in TemplatesA number of processor settings also support templating. Settings that support templating can have zero or moretemplate snippets. A template snippet begins with `{{` and ends with `}}`.Accessing fields and metafields in templates is exactly the same as via regular processor field settings.The following example adds a field named `field_c`. Its value is a concatenation ofthe values of `field_a` and `field_b`.[source,js]--------------------------------------------------{  "set": {    "field": "field_c"    "value": "{{field_a}} {{field_b}}"  }}--------------------------------------------------The following example uses the value of the `geoip.country_iso_code` field in the sourceto set the index that the document will be indexed into:[source,js]--------------------------------------------------{  "set": {    "field": "_index"    "value": "{{geoip.country_iso_code}}"  }}--------------------------------------------------[[handling-failure-in-pipelines]]== Handling Failures in PipelinesIn its simplest use case, a pipeline defines a list of processors thatare executed sequentially, and processing halts at the first exception. Thisbehavior may not be desirable when failures are expected. For example, you may have logsthat don't match the specified grok expression. Instead of halting execution, you maywant to index such documents into a separate index.To enable this behavior, you can use the `on_failure` parameter. The `on_failure` parameterdefines a list of processors to be executed immediately following the failed processor.You can specify this parameter at the pipeline level, as well as at the processorlevel. If a processor specifies an `on_failure` configuration, whetherit is empty or not, any exceptions that are thrown by the processor are caught, and thepipeline continues executing the remaining processors. Because you can define further processorswithin the scope of an `on_failure` statement, you can nest failure handling.The following example defines a pipeline that renames the `foo` field inthe processed document to `bar`. If the document does not contain the `foo` field, the processorattaches an error message to the document for later analysis withinElasticsearch.[source,js]--------------------------------------------------{  "description" : "my first pipeline with handled exceptions",  "processors" : [    {      "rename" : {        "field" : "foo",        "target_field" : "bar",        "on_failure" : [          {            "set" : {              "field" : "error",              "value" : "field \"foo\" does not exist, cannot rename to \"bar\""            }          }        ]      }    }  ]}--------------------------------------------------The following example defines an `on_failure` block on a whole pipeline to changethe index to which failed documents get sent.[source,js]--------------------------------------------------{  "description" : "my first pipeline with handled exceptions",  "processors" : [ ... ],  "on_failure" : [    {      "set" : {        "field" : "_index",        "value" : "failed-{{ _index }}"      }    }  ]}--------------------------------------------------Alternatively instead of defining behaviour in case of processor failure, it is also possibleto ignore a failure and continue with the next processor by specifying the `ignore_failure` setting.In case in the example below the field `foo` doesn't exist the failure will be caught and the pipelinecontinues to execute, which in this case means that the pipeline does nothing.[source,js]--------------------------------------------------{  "description" : "my first pipeline with handled exceptions",  "processors" : [    {      "rename" : {        "field" : "foo",        "target_field" : "bar",        "ignore_failure" : true      }    }  ]}--------------------------------------------------The `ignore_failure` can be set on any processor and defaults to `false`.[float][[accessing-error-metadata]]=== Accessing Error Metadata From Processors Handling ExceptionsYou may want to retrieve the actual error message that was thrownby a failed processor. To do so you can access metadata fields called`on_failure_message`, `on_failure_processor_type`, and `on_failure_processor_tag`. These fields are only accessiblefrom within the context of an `on_failure` block.Here is an updated version of the example that yousaw earlier. But instead of setting the error message manually, the example leverages the `on_failure_message`metadata field to provide the error message.[source,js]--------------------------------------------------{  "description" : "my first pipeline with handled exceptions",  "processors" : [    {      "rename" : {        "field" : "foo",        "to" : "bar",        "on_failure" : [          {            "set" : {              "field" : "error",              "value" : "{{ _ingest.on_failure_message }}"            }          }        ]      }    }  ]}--------------------------------------------------[[ingest-processors]]== ProcessorsAll processors are defined in the following way within a pipeline definition:[source,js]--------------------------------------------------{  "PROCESSOR_NAME" : {    ... processor configuration options ...  }}--------------------------------------------------Each processor defines its own configuration parameters, but all processors havethe ability to declare `tag` and `on_failure` fields. These fields are optional.A `tag` is simply a string identifier of the specific instantiation of a certainprocessor in a pipeline. The `tag` field does not affect the processor's behavior,but is very useful for bookkeeping and tracing errors to specific processors.See <<handling-failure-in-pipelines>> to learn more about the `on_failure` field and error handling in pipelines.The <<ingest-info,node info API>> can be used to figure out what processors are available in a cluster.The <<ingest-info,node info API>> will provide a per node list of what processors are available.Custom processors must be installed on all nodes. The put pipeline API will fail if a processor specified in a pipelinedoesn't exist on all nodes. If you rely on custom processor plugins make sure to mark these plugins as mandatory by adding`plugin.mandatory` setting to the `config/elasticsearch.yml` file, for example:[source,yaml]--------------------------------------------------plugin.mandatory: ingest-attachment,ingest-geoip--------------------------------------------------A node will not start if either of these plugins are not available.The <<ingest-stats,node stats API>> can be used to fetch ingest usage statistics, globally and on a perpipeline basis. Useful to find out which pipelines are used the most or spent the most time on preprocessing.[[append-processor]]=== Append ProcessorAppends one or more values to an existing array if the field already exists and it is an array.Converts a scalar to an array and appends one or more values to it if the field exists and it is a scalar.Creates an array containing the provided values if the field doesn't exist.Accepts a single value or an array of values.[[append-options]].Append Options[options="header"]|======| Name      | Required  | Default  | Description| `field`   | yes       | -        | The field to be appended to| `value`   | yes       | -        | The value to be appended|======[source,js]--------------------------------------------------{  "append": {    "field": "field1"    "value": ["item2", "item3", "item4"]  }}--------------------------------------------------[[convert-processor]]=== Convert ProcessorConverts an existing field's value to a different type, such as converting a string to an integer.If the field value is an array, all members will be converted.The supported types include: `integer`, `float`, `string`, `boolean`, and `auto`.Specifying `boolean` will set the field to true if its string value is equal to `true` (ignore case), tofalse if its string value is equal to `false` (ignore case), or it will throw an exception otherwise.Specifying `auto` will attempt to convert the string-valued `field` into the closest non-string type.For example, a field whose value is `"true"` will be converted to its respective boolean type: `true`. Anda value of `"242.15"` will "automatically" be converted to `242.15` of type `float`. If a provided field cannotbe appropriately converted, the Convert Processor will still process successfully and leave the field value as-is. Insuch a case, `target_field` will still be updated with the unconverted field value.[[convert-options]].Convert Options[options="header"]|======| Name             | Required  | Default  | Description| `field`          | yes       | -        | The field whose value is to be converted| `target_field`   | no        | `field`  | The field to assign the converted value to, by default `field` is updated in-place| `type`           | yes       | -        | The type to convert the existing value to| `ignore_missing` | no        | `false`  | If `true` and `field` does not exist or is `null`, the processor quietly exits without modifying the document|======[source,js]--------------------------------------------------{  "convert": {    "field" : "foo",    "type": "integer"  }}--------------------------------------------------[[date-processor]]=== Date ProcessorParses dates from fields, and then uses the date or timestamp as the timestamp for the document.By default, the date processor adds the parsed date as a new field called `@timestamp`. You can specify adifferent field by setting the `target_field` configuration parameter. Multiple date formats are supportedas part of the same date processor definition. They will be used sequentially to attempt parsing the date field,in the same order they were defined as part of the processor definition.[[date-options]].Date options[options="header"]|======| Name                   | Required  | Default             | Description| `field`                | yes       | -                   | The field to get the date from.| `target_field`         | no        | @timestamp          | The field that will hold the parsed date.| `formats`              | yes       | -                   | An array of the expected date formats. Can be a Joda pattern or one of the following formats: ISO8601, UNIX, UNIX_MS, or TAI64N.| `timezone`             | no        | UTC                 | The timezone to use when parsing the date.| `locale`               | no        | ENGLISH             | The locale to use when parsing the date, relevant when parsing month names or week days.|======Here is an example that adds the parsed date to the `timestamp` field based on the `initial_date` field:[source,js]--------------------------------------------------{  "description" : "...",  "processors" : [    {      "date" : {        "field" : "initial_date",        "target_field" : "timestamp",        "formats" : ["dd/MM/yyyy hh:mm:ss"],        "timezone" : "Europe/Amsterdam"      }    }  ]}--------------------------------------------------[[date-index-name-processor]]=== Date Index Name ProcessorThe purpose of this processor is to point documents to the right time based index basedon a date or timestamp field in a document by using the <<date-math-index-names, date math index name support>>.The processor sets the `_index` meta field with a date math index name expression based on the provided index nameprefix, a date or timestamp field in the documents being processed and the provided date rounding.First, this processor fetches the date or timestamp from a field in the document being processed. Optionally,date formatting can be configured on how the field's value should be parsed into a date. Then this date,the provided index name prefix and the provided date rounding get formatted into a date math index name expression.Also here optionally date formatting can be specified on how the date should be formatted into a date math index nameexpression.An example pipeline that points documents to a monthly index that starts with a `myindex-` prefix based on adate in the `date1` field:[source,js]--------------------------------------------------PUT _ingest/pipeline/monthlyindex{  "description": "monthly date-time index naming",  "processors" : [    {      "date_index_name" : {        "field" : "date1",        "index_name_prefix" : "myindex-",        "date_rounding" : "M"      }    }  ]}--------------------------------------------------// CONSOLEUsing that pipeline for an index request:[source,js]--------------------------------------------------PUT /myindex/type/1?pipeline=monthlyindex{  "date1" : "2016-04-25T12:02:01.789Z"}--------------------------------------------------// CONSOLE// TEST[continued][source,js]--------------------------------------------------{  "_index" : "myindex-2016-04-01",  "_type" : "type",  "_id" : "1",  "_version" : 1,  "result" : "created",  "_shards" : {    "total" : 2,    "successful" : 1,    "failed" : 0  },  "created" : true,  "_seq_no" : 0,  "_primary_term" : 1}--------------------------------------------------// TESTRESPONSEThe above request will not index this document into the `myindex` index, but into the `myindex-2016-04-01` index becauseit was rounded by month. This is because the date-index-name-processor overrides the `_index` property of the document.To see the date-math value of the index supplied in the actual index request which resulted in the above document beingindexed into `myindex-2016-04-01` we can inspect the effects of the processor using a simulate request.[source,js]--------------------------------------------------POST _ingest/pipeline/_simulate{  "pipeline" :  {    "description": "monthly date-time index naming",    "processors" : [      {        "date_index_name" : {          "field" : "date1",          "index_name_prefix" : "myindex-",          "date_rounding" : "M"        }      }    ]  },  "docs": [    {      "_source": {        "date1": "2016-04-25T12:02:01.789Z"      }    }  ]}--------------------------------------------------// CONSOLEand the result:[source,js]--------------------------------------------------{  "docs" : [    {      "doc" : {        "_id" : "_id",        "_index" : "<myindex-{2016-04-25||/M{yyyy-MM-dd|UTC}}>",        "_type" : "_type",        "_source" : {          "date1" : "2016-04-25T12:02:01.789Z"        },        "_ingest" : {          "timestamp" : "2016-11-08T19:43:03.850+0000"        }      }    }  ]}--------------------------------------------------// TESTRESPONSE[s/2016-11-08T19:43:03.850\+0000/$body.docs.0.doc._ingest.timestamp/]The above example shows that `_index` was set to `<myindex-{2016-04-25||/M{yyyy-MM-dd|UTC}}>`. Elasticsearchunderstands this to mean `2016-04-01` as is explained in the <<date-math-index-names, date math index name documentation>>[[date-index-name-options]].Date index name options[options="header"]|======| Name                   | Required  | Default                      | Description| `field`                | yes       | -                            | The field to get the date or timestamp from.| `index_name_prefix`    | no        | -                            | A prefix of the index name to be prepended before the printed date.| `date_rounding`        | yes       | -                            | How to round the date when formatting the date into the index name. Valid values are: `y` (year), `M` (month), `w` (week), `d` (day), `h` (hour), `m` (minute) and `s` (second).| `date_formats `        | no        | yyyy-MM-dd'T'HH:mm:ss.SSSZ   | An array of the expected date formats for parsing dates / timestamps in the document being preprocessed. Can be a Joda pattern or one of the following formats: ISO8601, UNIX, UNIX_MS, or TAI64N.| `timezone`             | no        | UTC                          | The timezone to use when parsing the date and when date math index supports resolves expressions into concrete index names.| `locale`               | no        | ENGLISH                      | The locale to use when parsing the date from the document being preprocessed, relevant when parsing month names or week days.| `index_name_format`    | no        | yyyy-MM-dd                   | The format to be used when printing the parsed date into the index name. An valid Joda pattern is expected here.|======[[fail-processor]]=== Fail ProcessorRaises an exception. This is useful for whenyou expect a pipeline to fail and want to relay a specific messageto the requester.[[fail-options]].Fail Options[options="header"]|======| Name       | Required  | Default  | Description| `message`  | yes       | -        | The error message of the `FailException` thrown by the processor|======[source,js]--------------------------------------------------{  "fail": {    "message": "an error message"  }}--------------------------------------------------[[foreach-processor]]=== Foreach Processorexperimental[This processor may change or be replaced by something else that provides similar functionality. Thisprocessor executes in its own context, which makes it different compared to all other processors and for features likeverbose simulation the subprocessor isn't visible. The reason we still expose this processor, is that it is the onlyprocessor that can operate on an array]Processes elements in an array of unknown length.All processors can operate on elements inside an array, but if all elements of an array need tobe processed in the same way, defining a processor for each element becomes cumbersome and trickybecause it is likely that the number of elements in an array is unknown. For this reason the `foreach`processor exists. By specifying the field holding array elements and a processor thatdefines what should happen to each element, array fields can easily be preprocessed.A processor inside the foreach processor works in the array element context and puts that in the ingest metadataunder the `_ingest._value` key. If the array element is a json object it holds all immediate fields of that json object.and if the nested object is a value is `_ingest._value` just holds that value. Note that if a processor prior to the`foreach` processor used `_ingest._value` key then the specified value will not be available to the processor insidethe `foreach` processor. The `foreach` processor does restore the original value, so that value is available to processorsafter the `foreach` processor.Note that any other field from the document are accessible and modifiable like with all other processors. This processorjust puts the current array element being read into `_ingest._value` ingest metadata attribute, so that it may bepre-processed.If the `foreach` processor fails to process an element inside the array, and no `on_failure` processor has been specified,then it aborts the execution and leaves the array unmodified.[[foreach-options]].Foreach Options[options="header"]|======| Name          | Required  | Default  | Description| `field`       | yes       | -        | The array field| `processor`   | yes       | -        | The processor to execute against each field|======Assume the following document:[source,js]--------------------------------------------------{  "values" : ["foo", "bar", "baz"]}--------------------------------------------------When this `foreach` processor operates on this sample document:[source,js]--------------------------------------------------{  "foreach" : {    "field" : "values",    "processor" : {      "uppercase" : {        "field" : "_ingest._value"      }    }  }}--------------------------------------------------Then the document will look like this after preprocessing:[source,js]--------------------------------------------------{  "values" : ["FOO", "BAR", "BAZ"]}--------------------------------------------------Let's take a look at another example:[source,js]--------------------------------------------------{  "persons" : [    {      "id" : "1",      "name" : "John Doe"    },    {      "id" : "2",      "name" : "Jane Doe"    }  ]}--------------------------------------------------In this case, the `id` field needs to be removed,so the following `foreach` processor is used:[source,js]--------------------------------------------------{  "foreach" : {    "field" : "persons",    "processor" : {      "remove" : {        "field" : "_ingest._value.id"      }    }  }}--------------------------------------------------After preprocessing the result is:[source,js]--------------------------------------------------{  "persons" : [    {      "name" : "John Doe"    },    {      "name" : "Jane Doe"    }  ]}--------------------------------------------------The wrapped processor can have a `on_failure` definition.For example, the `id` field may not exist on all person objects.Instead of failing the index request, you can use an `on_failure`block to send the document to the 'failure_index' index for later inspection:[source,js]--------------------------------------------------{  "foreach" : {    "field" : "persons",    "processor" : {      "remove" : {        "field" : "_value.id",        "on_failure" : [          {            "set" : {              "field", "_index",              "value", "failure_index"            }          }        ]      }    }  }}--------------------------------------------------In this example, if the `remove` processor does fail, thenthe array elements that have been processed thus far willbe updated.Another advanced example can be found in the {plugins}/ingest-attachment-with-arrays.html[attachment processor documentation].[[grok-processor]]=== Grok ProcessorExtracts structured fields out of a single text field within a document. You choose which field toextract matched fields from, as well as the grok pattern you expect will match. A grok pattern is like a regularexpression that supports aliased expressions that can be reused.This tool is perfect for syslog logs, apache and other webserver logs, mysql logs, and in general, any log formatthat is generally written for humans and not computer consumption.This processor comes packaged with overhttps://github.com/elastic/elasticsearch/tree/master/modules/ingest-common/src/main/resources/patterns[120 reusable patterns].If you need help building patterns to match your logs, you will find the <http://grokdebug.herokuapp.com> and<http://grokconstructor.appspot.com/> applications quite useful![[grok-basics]]==== Grok BasicsGrok sits on top of regular expressions, so any regular expressions are valid in grok as well.The regular expression library is Oniguruma, and you can see the full supported regexp syntaxhttps://github.com/kkos/oniguruma/blob/master/doc/RE[on the Onigiruma site].Grok works by leveraging this regular expression language to allow naming existing patterns and combining them into morecomplex patterns that match your fields.The syntax for reusing a grok pattern comes in three forms: `%{SYNTAX:SEMANTIC}`, `%{SYNTAX}`, `%{SYNTAX:SEMANTIC:TYPE}`.The `SYNTAX` is the name of the pattern that will match your text. For example, `3.44` will be matched by the `NUMBER`pattern and `55.3.244.1` will be matched by the `IP` pattern. The syntax is how you match. `NUMBER` and `IP` are bothpatterns that are provided within the default patterns set.The `SEMANTIC` is the identifier you give to the piece of text being matched. For example, `3.44` could be theduration of an event, so you could call it simply `duration`. Further, a string `55.3.244.1` might identifythe `client` making a request.The `TYPE` is the type you wish to cast your named field. `int` and `float` are currently the only types supported for coercion.For example, you might want to match the following text:[source,js]--------------------------------------------------3.44 55.3.244.1--------------------------------------------------You may know that the message in the example is a number followed by an IP address. You can match this text by using the followingGrok expression.[source,js]--------------------------------------------------%{NUMBER:duration} %{IP:client}--------------------------------------------------[[using-grok]]==== Using the Grok Processor in a Pipeline[[grok-options]].Grok Options[options="header"]|======| Name                   | Required  | Default             | Description| `field`                | yes       | -                   | The field to use for grok expression parsing| `patterns`             | yes       | -                   | An ordered list of grok expression to match and extract named captures with. Returns on the first expression in the list that matches.| `pattern_definitions`  | no        | -                   | A map of pattern-name and pattern tuples defining custom patterns to be used by the current processor. Patterns matching existing names will override the pre-existing definition.| `trace_match`          | no        | false               | when true, `_ingest._grok_match_index` will be inserted into your matched document's metadata with the index into the pattern found in `patterns` that matched.| `ignore_missing`       | no        | false               | If `true` and `field` does not exist or is `null`, the processor quietly exits without modifying the document|======Here is an example of using the provided patterns to extract out and name structured fields from a string field ina document.[source,js]--------------------------------------------------{  "message": "55.3.244.1 GET /index.html 15824 0.043"}--------------------------------------------------The pattern for this could be:[source,js]--------------------------------------------------%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}--------------------------------------------------Here is an example pipeline for processing the above document by using Grok:[source,js]--------------------------------------------------{  "description" : "...",  "processors": [    {      "grok": {        "field": "message",        "patterns": ["%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}"]      }    }  ]}--------------------------------------------------This pipeline will insert these named captures as new fields within the document, like so:[source,js]--------------------------------------------------{  "message": "55.3.244.1 GET /index.html 15824 0.043",  "client": "55.3.244.1",  "method": "GET",  "request": "/index.html",  "bytes": 15824,  "duration": "0.043"}--------------------------------------------------[[custom-patterns]]==== Custom Patterns and Pattern FilesThe Grok processor comes pre-packaged with a base set of pattern. These patterns may not always havewhat you are looking for. Pattern have a very basic format. Each entry describes has a name and the pattern itself.You can add your own patterns to a processor definition under the `pattern_definitions` option.Here is an example of a pipeline specifying custom pattern definitions:[source,js]--------------------------------------------------{  "description" : "...",  "processors": [    {      "grok": {        "field": "message",        "patterns": ["my %{FAVORITE_DOG:dog} is colored %{RGB:color}"]        "pattern_definitions" : {          "FAVORITE_DOG" : "beagle",          "RGB" : "RED|GREEN|BLUE"        }      }    }  ]}--------------------------------------------------[[trace-match]]==== Providing Multiple Match PatternsSometimes one pattern is not enough to capture the potential structure of a field. Let's assume wewant to match all messages that contain your favorite pet breeds of either cats or dogs. One way to accomplishthis is to provide two distinct patterns that can be matched, instead of one really complicated expression capturingthe same `or` behavior.Here is an example of such a configuration executed against the simulate API:[source,js]--------------------------------------------------POST _ingest/pipeline/_simulate{  "pipeline": {  "description" : "parse multiple patterns",  "processors": [    {      "grok": {        "field": "message",        "patterns": ["%{FAVORITE_DOG:pet}", "%{FAVORITE_CAT:pet}"],        "pattern_definitions" : {          "FAVORITE_DOG" : "beagle",          "FAVORITE_CAT" : "burmese"        }      }    }  ]},"docs":[  {    "_source": {      "message": "I love burmese cats!"    }  }  ]}--------------------------------------------------// CONSOLEresponse:[source,js]--------------------------------------------------{  "docs": [    {      "doc": {        "_type": "_type",        "_index": "_index",        "_id": "_id",        "_source": {          "message": "I love burmese cats!",          "pet": "burmese"        },        "_ingest": {          "timestamp": "2016-11-08T19:43:03.850+0000"        }      }    }  ]}--------------------------------------------------// TESTRESPONSE[s/2016-11-08T19:43:03.850\+0000/$body.docs.0.doc._ingest.timestamp/]Both patterns will set the field `pet` with the appropriate match, but what if we want to trace which of ourpatterns matched and populated our fields? We can do this with the `trace_match` parameter. Here is the output ofthat same pipeline, but with `"trace_match": true` configured:////Hidden setup for example:[source,js]--------------------------------------------------POST _ingest/pipeline/_simulate{  "pipeline": {  "description" : "parse multiple patterns",  "processors": [    {      "grok": {        "field": "message",        "patterns": ["%{FAVORITE_DOG:pet}", "%{FAVORITE_CAT:pet}"],        "trace_match": true,        "pattern_definitions" : {          "FAVORITE_DOG" : "beagle",          "FAVORITE_CAT" : "burmese"        }      }    }  ]},"docs":[  {    "_source": {      "message": "I love burmese cats!"    }  }  ]}--------------------------------------------------// CONSOLE////[source,js]--------------------------------------------------{  "docs": [    {      "doc": {        "_type": "_type",        "_index": "_index",        "_id": "_id",        "_source": {          "message": "I love burmese cats!",          "pet": "burmese"        },        "_ingest": {          "_grok_match_index": "1",          "timestamp": "2016-11-08T19:43:03.850+0000"        }      }    }  ]}--------------------------------------------------// TESTRESPONSE[s/2016-11-08T19:43:03.850\+0000/$body.docs.0.doc._ingest.timestamp/]In the above response, you can see that the index of the pattern that matched was `"1"`. This is to say that it was thesecond (index starts at zero) pattern in `patterns` to match.This trace metadata enables debugging which of the patterns matched. This information is stored in the ingestmetadata and will not be indexed.[[gsub-processor]]=== Gsub ProcessorConverts a string field by applying a regular expression and a replacement.If the field is not a string, the processor will throw an exception.[[gsub-options]].Gsub Options[options="header"]|======| Name          | Required  | Default  | Description| `field`       | yes       | -        | The field to apply the replacement to| `pattern`     | yes       | -        | The pattern to be replaced| `replacement` | yes       | -        | The string to replace the matching patterns with|======[source,js]--------------------------------------------------{  "gsub": {    "field": "field1",    "pattern": "\.",    "replacement": "-"  }}--------------------------------------------------[[join-processor]]=== Join ProcessorJoins each element of an array into a single string using a separator character between each element.Throws an error when the field is not an array.[[join-options]].Join Options[options="header"]|======| Name          | Required  | Default  | Description| `field`       | yes       | -        | The field to be separated| `separator`   | yes       | -        | The separator character|======[source,js]--------------------------------------------------{  "join": {    "field": "joined_array_field",    "separator": "-"  }}--------------------------------------------------[[json-processor]]=== JSON ProcessorConverts a JSON string into a structured JSON object.[[json-options]].Json Options[options="header"]|======| Name           | Required  | Default  | Description| `field`        | yes       | -        | The field to be parsed| `target_field` | no        | `field`  | The field to insert the converted structured object into| `add_to_root`  | no        | false    | Flag that forces the serialized json to be injected into the top level of the document. `target_field` must not be set when this option is chosen.|======Suppose you provide this configuration of the `json` processor:[source,js]--------------------------------------------------{  "json" : {    "field" : "string_source",    "target_field" : "json_target"  }}--------------------------------------------------If the following document is processed:[source,js]--------------------------------------------------{  "string_source": "{\"foo\": 2000}"}--------------------------------------------------after the `json` processor operates on it, it will look like:[source,js]--------------------------------------------------{  "string_source": "{\"foo\": 2000}",  "json_target": {    "foo": 2000  }}--------------------------------------------------If the following configuration is provided, omitting the optional `target_field` setting:[source,js]--------------------------------------------------{  "json" : {    "field" : "source_and_target"  }}--------------------------------------------------then after the `json` processor operates on this document:[source,js]--------------------------------------------------{  "source_and_target": "{\"foo\": 2000}"}--------------------------------------------------it will look like:[source,js]--------------------------------------------------{  "source_and_target": {    "foo": 2000  }}--------------------------------------------------This illustrates that, unless it is explicitly named in the processor configuration, the `target_field` is the same field provided in the required `field` configuration.[[kv-processor]]=== KV ProcessorThis processor helps automatically parse messages (or specific event fields) which are of the foo=bar variety.For example, if you have a log message which contains `ip=1.2.3.4 error=REFUSED`, you can parse those automatically by configuring:[source,js]--------------------------------------------------{  "kv": {    "field": "message",    "field_split": " ",    "value_split": "="  }}--------------------------------------------------[[kv-options]].Kv Options[options="header"]|======| Name             | Required  | Default  | Description| `field`          | yes       | -        | The field to be parsed| `field_split`    | yes       | -        | Regex pattern to use for splitting key-value pairs| `value_split`    | yes       | -        | Regex pattern to use for splitting the key from the value within a key-value pair| `target_field`   | no        | `null`   | The field to insert the extracted keys into. Defaults to the root of the document| `include_keys`   | no        | `null`   | List of keys to filter and insert into document. Defaults to including all keys| `ignore_missing` | no        | `false`  | If `true` and `field` does not exist or is `null`, the processor quietly exits without modifying the document|======[[lowercase-processor]]=== Lowercase ProcessorConverts a string to its lowercase equivalent.[[lowercase-options]].Lowercase Options[options="header"]|======| Name             | Required  | Default  | Description| `field`          | yes       | -        | The field to make lowercase| `ignore_missing` | no        | `false`  | If `true` and `field` does not exist or is `null`, the processor quietly exits without modifying the document|======[source,js]--------------------------------------------------{  "lowercase": {    "field": "foo"  }}--------------------------------------------------[[remove-processor]]=== Remove ProcessorRemoves an existing field. If the field doesn't exist, an exception will be thrown.[[remove-options]].Remove Options[options="header"]|======| Name      | Required  | Default  | Description| `field`   | yes       | -        | The field to be removed|======[source,js]--------------------------------------------------{  "remove": {    "field": "foo"  }}--------------------------------------------------[[rename-processor]]=== Rename ProcessorRenames an existing field. If the field doesn't exist or the new name is already used, an exception will be thrown.[[rename-options]].Rename Options[options="header"]|======| Name             | Required  | Default  | Description| `field`          | yes       | -        | The field to be renamed| `target_field`   | yes       | -        | The new name of the field| `ignore_missing` | no        | `false`  | If `true` and `field` does not exist, the processor quietly exits without modifying the document|======[source,js]--------------------------------------------------{  "rename": {    "field": "foo",    "target_field": "foobar"  }}--------------------------------------------------[[script-processor]]=== Script ProcessorAllows inline, stored, and file scripts to be executed within ingest pipelines.See <<modules-scripting-using, How to use scripts>> to learn more about writing scripts. The Script Processorleverages caching of compiled scripts for improved performance. Since thescript specified within the processor is potentially re-compiled per document, it is importantto understand how script caching works. To learn more aboutcaching see <<modules-scripting-using-caching, Script Caching>>.[[script-options]].Script Options[options="header"]|======| Name                   | Required  | Default    | Description| `lang`                 | no        | "painless" | The scripting language| `file`                 | no        | -          | The script file to refer to| `id`                   | no        | -          | The stored script id to refer to| `inline`               | no        | -          | An inline script to be executed| `params`               | no        | -          | Script Parameters|======One of `file`, `id`, `inline` options must be provided in order to properly reference a script to execute.You can access the current ingest document from within the script context by using the `ctx` variable.The following example sets a new field called `field_a_plus_b_times_c` to be the sum of two existingnumeric fields `field_a` and `field_b` multiplied by the parameter param_c:[source,js]--------------------------------------------------{  "script": {    "lang": "painless",    "inline": "ctx.field_a_plus_b_times_c = (ctx.field_a + ctx.field_b) * params.param_c",    "params": {      "param_c": 10    }  }}--------------------------------------------------[[set-processor]]=== Set ProcessorSets one field and associates it with the specified value. If the field already exists,its value will be replaced with the provided one.[[set-options]].Set Options[options="header"]|======| Name      | Required  | Default  | Description| `field`   | yes       | -        | The field to insert, upsert, or update| `value`   | yes       | -        | The value to be set for the field| `override`| no        | true     | If processor will update fields with pre-existing non-null-valued field. When set to `false`, such fields will not be touched.|======[source,js]--------------------------------------------------{  "set": {    "field": "field1",    "value": 582.1  }}--------------------------------------------------[[split-processor]]=== Split ProcessorSplits a field into an array using a separator character. Only works on string fields.[[split-options]].Split Options[options="header"]|======| Name              | Required  | Default  | Description| `field`           | yes       | -        | The field to split| `separator`       | yes       | -        | A regex which matches the separator, eg `,` or `\s+`| `ignore_missing`  | no        | `false`  | If `true` and `field` does not exist, the processor quietly exits without modifying the document|======[source,js]--------------------------------------------------{  "split": {    "field": "my_field",    "separator": "\\s+" <1>  }}--------------------------------------------------<1> Treat all consecutive whitespace characters as a single separator[[sort-processor]]=== Sort ProcessorSorts the elements of an array ascending or descending.  Homogeneous arrays of numbers will be sortednumerically, while arrays of strings or heterogeneous arrays of strings + numbers will be sorted lexicographically.Throws an error when the field is not an array.[[sort-options]].Sort Options[options="header"]|======| Name    | Required  | Default  | Description| `field` | yes       | -        | The field to be sorted| `order` | no        | `"asc"`  | The sort order to use. Accepts `"asc"` or `"desc"`.|======[source,js]--------------------------------------------------{  "sort": {    "field": "field_to_sort",    "order": "desc"  }}--------------------------------------------------[[trim-processor]]=== Trim ProcessorTrims whitespace from field.NOTE: This only works on leading and trailing whitespace.[[trim-options]].Trim Options[options="header"]|======| Name              | Required  | Default  | Description| `field`           | yes       | -        | The string-valued field to trim whitespace from| `ignore_missing`  | no        | `false`  | If `true` and `field` does not exist, the processor quietly exits without modifying the document|======[source,js]--------------------------------------------------{  "trim": {    "field": "foo"  }}--------------------------------------------------[[uppercase-processor]]=== Uppercase ProcessorConverts a string to its uppercase equivalent.[[uppercase-options]].Uppercase Options[options="header"]|======| Name             | Required  | Default  | Description| `field`          | yes       | -        | The field to make uppercase| `ignore_missing` | no        | `false`  | If `true` and `field` does not exist or is `null`, the processor quietly exits without modifying the document|======[source,js]--------------------------------------------------{  "uppercase": {    "field": "foo"  }}--------------------------------------------------[[dot-expand-processor]]=== Dot Expander ProcessorExpands a field with dots into an object field. This processor allows fieldswith dots in the name to be accessible by other processors in the pipeline.Otherwise these <<accessing-data-in-pipelines,fields>> can't be accessed by any processor.[[dot-expender-options]].Dot Expand Options[options="header"]|======| Name     | Required  | Default  | Description| `field`  | yes       | -        | The field to expand into an object field| `path`   | no        | -        | The field that contains the field to expand. Only required if the field to expand is part another object field, because the `field` option can only understand leaf fields.|======[source,js]--------------------------------------------------{  "dot_expander": {    "field": "foo.bar"  }}--------------------------------------------------For example the dot expand processor would turn this document:[source,js]--------------------------------------------------{  "foo.bar" : "value"}--------------------------------------------------into:[source,js]--------------------------------------------------{  "foo" : {     "bar" : "value"  }}--------------------------------------------------If there is already a `bar` field nested under `foo` thenthis processor merges the the `foo.bar` field into it. If the field isa scalar value then it will turn that field into an array field.For example, the following document:[source,js]--------------------------------------------------{  "foo.bar" : "value2",  "foo" : {    "bar" : "value1"  }}--------------------------------------------------is transformed by the `dot_expander` processor into:[source,js]--------------------------------------------------{  "foo" : {    "bar" : ["value1", "value2"]  }}--------------------------------------------------If any field outside of the leaf field conflicts with a pre-existing field of the same name,then that field needs to be renamed first.Consider the following document:[source,js]--------------------------------------------------{  "foo": "value1",  "foo.bar": "value2"}--------------------------------------------------Then the the `foo` needs to be renamed first before the `dot_expander`processor is applied. So in order for the `foo.bar` field to properlybe expanded into the `bar` field under the `foo` field the followingpipeline should be used:[source,js]--------------------------------------------------{  "processors" : [    {      "rename" : {        "field" : "foo",        "target_field" : "foo.bar""      }    },    {      "dot_expander": {        "field": "foo.bar"      }    }  ]}--------------------------------------------------The reason for this is that Ingest doesn't know how to automatically casta scalar field to an object field.
 |