foreach.asciidoc 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. [[foreach-processor]]
  2. === Foreach processor
  3. ++++
  4. <titleabbrev>Foreach</titleabbrev>
  5. ++++
  6. Runs an ingest processor on each element of an array or object.
  7. All ingest processors can run on array or object elements. However, if the
  8. number of elements is unknown, it can be cumbersome to process each one in the
  9. same way.
  10. The `foreach` processor lets you specify a `field` containing array or object
  11. values and a `processor` to run on each element in the field.
  12. [[foreach-options]]
  13. .Foreach Options
  14. [options="header"]
  15. |======
  16. | Name | Required | Default | Description
  17. | `field` | yes | - | Field containing array or object
  18. values.
  19. | `processor` | yes | - | Ingest processor to run on each
  20. element.
  21. | `ignore_missing` | no | false | If `true`, the processor silently
  22. exits without changing the document if the `field` is `null` or missing.
  23. include::common-options.asciidoc[]
  24. |======
  25. [discrete]
  26. [[foreach-keys-values]]
  27. ==== Access keys and values
  28. When iterating through an array or object, the `foreach` processor stores the
  29. current element's value in the `_ingest._value` <<access-ingest-metadata,ingest
  30. metadata>> field. `_ingest._value` contains the entire element value, including
  31. any child fields. You can access child field values using dot notation on the
  32. `_ingest._value` field.
  33. When iterating through an object, the `foreach` processor also stores the
  34. current element's key as a string in `_ingest._key`.
  35. You can access and change `_ingest._key` and `_ingest._value` in the
  36. `processor`. For an example, see the <<foreach-object-ex, object
  37. example>>.
  38. [discrete]
  39. [[foreach-failure-handling]]
  40. ==== Failure handling
  41. If the `foreach` processor fails to process an element and no `on_failure`
  42. processor is specified, the `foreach` processor silently exits. This leaves the
  43. entire array or object value unchanged.
  44. [discrete]
  45. [[foreach-examples]]
  46. ==== Examples
  47. The following examples show how you can use the `foreach` processor with
  48. different data types and options:
  49. * <<foreach-array-ex>>
  50. * <<foreach-array-objects-ex>>
  51. * <<foreach-object-ex>>
  52. * <<failure-handling-ex>>
  53. [discrete]
  54. [[foreach-array-ex]]
  55. ===== Array
  56. Assume the following document:
  57. [source,js]
  58. --------------------------------------------------
  59. {
  60. "values" : ["foo", "bar", "baz"]
  61. }
  62. --------------------------------------------------
  63. // NOTCONSOLE
  64. When this `foreach` processor operates on this sample document:
  65. [source,js]
  66. --------------------------------------------------
  67. {
  68. "foreach" : {
  69. "field" : "values",
  70. "processor" : {
  71. "uppercase" : {
  72. "field" : "_ingest._value"
  73. }
  74. }
  75. }
  76. }
  77. --------------------------------------------------
  78. // NOTCONSOLE
  79. Then the document will look like this after processing:
  80. [source,js]
  81. --------------------------------------------------
  82. {
  83. "values" : ["FOO", "BAR", "BAZ"]
  84. }
  85. --------------------------------------------------
  86. // NOTCONSOLE
  87. [discrete]
  88. [[foreach-array-objects-ex]]
  89. ===== Array of objects
  90. Assume the following document:
  91. [source,js]
  92. --------------------------------------------------
  93. {
  94. "persons" : [
  95. {
  96. "id" : "1",
  97. "name" : "John Doe"
  98. },
  99. {
  100. "id" : "2",
  101. "name" : "Jane Doe"
  102. }
  103. ]
  104. }
  105. --------------------------------------------------
  106. // NOTCONSOLE
  107. In this case, the `id` field needs to be removed,
  108. so the following `foreach` processor is used:
  109. [source,js]
  110. --------------------------------------------------
  111. {
  112. "foreach" : {
  113. "field" : "persons",
  114. "processor" : {
  115. "remove" : {
  116. "field" : "_ingest._value.id"
  117. }
  118. }
  119. }
  120. }
  121. --------------------------------------------------
  122. // NOTCONSOLE
  123. After processing the result is:
  124. [source,js]
  125. --------------------------------------------------
  126. {
  127. "persons" : [
  128. {
  129. "name" : "John Doe"
  130. },
  131. {
  132. "name" : "Jane Doe"
  133. }
  134. ]
  135. }
  136. --------------------------------------------------
  137. // NOTCONSOLE
  138. For another array of objects example, see
  139. {plugins}/ingest-attachment-with-arrays.html[attachment processor
  140. documentation].
  141. [discrete]
  142. [[foreach-object-ex]]
  143. ===== Object
  144. You can also use the `foreach` processor on object fields. For example,
  145. the following document contains a `products` field with object values.
  146. [source,js]
  147. --------------------------------------------------
  148. {
  149. "products" : {
  150. "widgets" : {
  151. "total_sales" : 50,
  152. "unit_price": 1.99,
  153. "display_name": ""
  154. },
  155. "sprockets" : {
  156. "total_sales" : 100,
  157. "unit_price": 9.99,
  158. "display_name": "Super Sprockets"
  159. },
  160. "whizbangs" : {
  161. "total_sales" : 200,
  162. "unit_price": 19.99,
  163. "display_name": "Wonderful Whizbangs"
  164. }
  165. }
  166. }
  167. --------------------------------------------------
  168. // NOTCONSOLE
  169. The following `foreach` processor changes the value of `products.display_name`
  170. to uppercase.
  171. [source,js]
  172. --------------------------------------------------
  173. {
  174. "foreach": {
  175. "field": "products",
  176. "processor": {
  177. "uppercase": {
  178. "field": "_ingest._value.display_name"
  179. }
  180. }
  181. }
  182. }
  183. --------------------------------------------------
  184. // NOTCONSOLE
  185. When run on the document, the `foreach` processor returns:
  186. [source,js]
  187. --------------------------------------------------
  188. {
  189. "products" : {
  190. "widgets" : {
  191. "total_sales" : 50,
  192. "unit_price" : 1.99,
  193. "display_name" : ""
  194. },
  195. "sprockets" : {
  196. "total_sales" : 100,
  197. "unit_price" : 9.99,
  198. "display_name" : "SUPER SPROCKETS"
  199. },
  200. "whizbangs" : {
  201. "total_sales" : 200,
  202. "unit_price" : 19.99,
  203. "display_name" : "WONDERFUL WHIZBANGS"
  204. }
  205. }
  206. }
  207. --------------------------------------------------
  208. // NOTCONSOLE
  209. The following `foreach` processor sets each element's key to the
  210. value of `products.display_name`. If `products.display_name` contains an empty string,
  211. the processor deletes the element.
  212. [source,js]
  213. --------------------------------------------------
  214. {
  215. "foreach": {
  216. "field": "products",
  217. "processor": {
  218. "set": {
  219. "field": "_ingest._key",
  220. "value": "{{_ingest._value.display_name}}"
  221. }
  222. }
  223. }
  224. }
  225. --------------------------------------------------
  226. // NOTCONSOLE
  227. When run on the previous document, the `foreach` processor returns:
  228. [source,js]
  229. --------------------------------------------------
  230. {
  231. "products" : {
  232. "Wonderful Whizbangs" : {
  233. "total_sales" : 200,
  234. "unit_price" : 19.99,
  235. "display_name" : "Wonderful Whizbangs"
  236. },
  237. "Super Sprockets" : {
  238. "total_sales" : 100,
  239. "unit_price" : 9.99,
  240. "display_name" : "Super Sprockets"
  241. }
  242. }
  243. }
  244. --------------------------------------------------
  245. // NOTCONSOLE
  246. [discrete]
  247. [[failure-handling-ex]]
  248. ===== Failure handling
  249. The wrapped processor can have a `on_failure` definition.
  250. For example, the `id` field may not exist on all person objects.
  251. Instead of failing the index request, you can use an `on_failure`
  252. block to send the document to the 'failure_index' index for later inspection:
  253. [source,js]
  254. --------------------------------------------------
  255. {
  256. "foreach" : {
  257. "field" : "persons",
  258. "processor" : {
  259. "remove" : {
  260. "field" : "_value.id",
  261. "on_failure" : [
  262. {
  263. "set" : {
  264. "field": "_index",
  265. "value": "failure_index"
  266. }
  267. }
  268. ]
  269. }
  270. }
  271. }
  272. }
  273. --------------------------------------------------
  274. // NOTCONSOLE
  275. In this example, if the `remove` processor does fail, then
  276. the array elements that have been processed thus far will
  277. be updated.