Browse Source

[DOCS] Map iteration support in ForEach processor (#76972)

Dan Hermann 4 years ago
parent
commit
c4aad2965f
1 changed files with 184 additions and 27 deletions
  1. 184 27
      docs/reference/ingest/processors/foreach.asciidoc

+ 184 - 27
docs/reference/ingest/processors/foreach.asciidoc

@@ -4,39 +4,70 @@
 <titleabbrev>Foreach</titleabbrev>
 ++++
 
-Processes elements in an array of unknown length.
+Runs an ingest processor on each element of an array or object.
 
-All processors can operate on elements inside an array, but if all elements of an array need to
-be processed in the same way, defining a processor for each element becomes cumbersome and tricky
-because 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 that
-defines what should happen to each element, array fields can easily be preprocessed.
+All ingest processors can run on array or object elements. However, if the
+number of elements is unknown, it can be cumbersome to process each one in the
+same way.
 
-A processor inside the foreach processor works in the array element context and puts that in the ingest metadata
-under 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 inside
-the `foreach` processor. The `foreach` processor does restore the original value, so that value is available to processors
-after the `foreach` processor.
-
-Note that any other field from the document are accessible and modifiable like with all other processors. This processor
-just puts the current array element being read into `_ingest._value` ingest metadata attribute, so that it may be
-pre-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.
+The `foreach` processor lets you specify a `field` containing array or object
+values and a `processor` to run on each element in the field.
 
 [[foreach-options]]
 .Foreach Options
 [options="header"]
 |======
 | Name             | Required  | Default  | Description
-| `field`          | yes       | -        | The array field
-| `processor`      | yes       | -        | The processor to execute against each field
-| `ignore_missing` | no        | false    | If `true` and `field` does not exist or is `null`, the processor quietly exits without modifying the document
+| `field`          | yes       | -        | Field containing array or object
+values.
+| `processor`      | yes       | -        | Ingest processor to run on each
+element.
+| `ignore_missing` | no        | false    | If `true`, the processor silently
+exits without changing the document if the `field` is `null` or missing.
 include::common-options.asciidoc[]
 |======
 
+[discrete]
+[[foreach-keys-values]]
+==== Access keys and values
+
+When iterating through an array or object, the `foreach` processor stores the
+current element's value in the `_ingest._value` <<access-ingest-metadata,ingest
+metadata>> field. `_ingest._value` contains the entire element value, including
+any child fields. You can access child field values using dot notation on the
+`_ingest._value` field.
+
+When iterating through an object, the `foreach` processor also stores the
+current element's key as a string in `_ingest._key`.
+
+You can access and change `_ingest._key` and `_ingest._value` in the
+`processor`. For an example, see the <<foreach-object-ex, object
+example>>.
+
+[discrete]
+[[foreach-failure-handling]]
+==== Failure handling
+
+If the `foreach` processor fails to process an element and no `on_failure`
+processor is specified, the `foreach` processor silently exits. This leaves the
+entire array or object value unchanged.
+
+[discrete]
+[[foreach-examples]]
+==== Examples
+
+The following examples show how you can use the `foreach` processor with
+different data types and options:
+
+* <<foreach-array-ex>>
+* <<foreach-array-objects-ex>>
+* <<foreach-object-ex>>
+* <<failure-handling-ex>>
+
+[discrete]
+[[foreach-array-ex]]
+===== Array
+
 Assume the following document:
 
 [source,js]
@@ -64,7 +95,7 @@ When this `foreach` processor operates on this sample document:
 --------------------------------------------------
 // NOTCONSOLE
 
-Then the document will look like this after preprocessing:
+Then the document will look like this after processing:
 
 [source,js]
 --------------------------------------------------
@@ -74,7 +105,11 @@ Then the document will look like this after preprocessing:
 --------------------------------------------------
 // NOTCONSOLE
 
-Let's take a look at another example:
+[discrete]
+[[foreach-array-objects-ex]]
+===== Array of objects
+
+Assume the following document:
 
 [source,js]
 --------------------------------------------------
@@ -111,7 +146,7 @@ so the following `foreach` processor is used:
 --------------------------------------------------
 // NOTCONSOLE
 
-After preprocessing the result is:
+After processing the result is:
 
 [source,js]
 --------------------------------------------------
@@ -128,6 +163,130 @@ After preprocessing the result is:
 --------------------------------------------------
 // NOTCONSOLE
 
+For another array of objects example, see
+{plugins}/ingest-attachment-with-arrays.html[attachment processor
+documentation].
+
+[discrete]
+[[foreach-object-ex]]
+===== Object
+
+You can also use the `foreach` processor on object fields. For example,
+the following document contains a `products` field with object values.
+
+[source,js]
+--------------------------------------------------
+{
+  "products" : {
+    "widgets" : {
+      "total_sales" : 50,
+      "unit_price": 1.99,
+      "display_name": ""
+    },
+    "sprockets" : {
+      "total_sales" : 100,
+      "unit_price": 9.99,
+      "display_name": "Super Sprockets"
+    },
+    "whizbangs" : {
+      "total_sales" : 200,
+      "unit_price": 19.99,
+      "display_name": "Wonderful Whizbangs"
+    }
+  }
+}
+--------------------------------------------------
+// NOTCONSOLE
+
+The following `foreach` processor changes the value of `products.display_name`
+to uppercase.
+
+[source,js]
+--------------------------------------------------
+{
+  "foreach": {
+    "field": "products",
+    "processor": {
+      "uppercase": {
+        "field": "_ingest._value.display_name"
+      }
+    }
+  }
+}
+--------------------------------------------------
+// NOTCONSOLE
+
+When run on the document, the `foreach` processor returns:
+
+[source,js]
+--------------------------------------------------
+{
+  "products" : {
+    "widgets" : {
+      "total_sales" : 50,
+      "unit_price" : 1.99,
+      "display_name" : ""
+    },
+    "sprockets" : {
+      "total_sales" : 100,
+      "unit_price" : 9.99,
+      "display_name" : "SUPER SPROCKETS"
+    },
+    "whizbangs" : {
+      "total_sales" : 200,
+      "unit_price" : 19.99,
+      "display_name" : "WONDERFUL WHIZBANGS"
+    }
+  }
+}
+--------------------------------------------------
+// NOTCONSOLE
+
+The following `foreach` processor sets each element's key to the
+value of `products.display_name`. If `products.display_name` contains an empty string,
+the processor deletes the element.
+
+[source,js]
+--------------------------------------------------
+{
+  "foreach": {
+    "field": "products",
+    "processor": {
+      "set": {
+        "field": "_ingest._key",
+        "value": "{{_ingest._value.display_name}}"
+      }
+    }
+  }
+}
+--------------------------------------------------
+// NOTCONSOLE
+
+When run on the previous document, the `foreach` processor returns:
+
+[source,js]
+--------------------------------------------------
+{
+  "products" : {
+    "Wonderful Whizbangs" : {
+      "total_sales" : 200,
+      "unit_price" : 19.99,
+      "display_name" : "Wonderful Whizbangs"
+    },
+    "Super Sprockets" : {
+      "total_sales" : 100,
+      "unit_price" : 9.99,
+      "display_name" : "Super Sprockets"
+    }
+  }
+}
+--------------------------------------------------
+// NOTCONSOLE
+
+[discrete]
+[[failure-handling-ex]]
+===== Failure handling
+
 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`
@@ -159,5 +318,3 @@ block to send the document to the 'failure_index' index for later inspection:
 In this example, if the `remove` processor does fail, then
 the array elements that have been processed thus far will
 be updated.
-
-Another advanced example can be found in the {plugins}/ingest-attachment-with-arrays.html[attachment processor documentation].