ingest-attachment.asciidoc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. [[ingest-attachment]]
  2. === Ingest Attachment Processor Plugin
  3. The ingest attachment plugin lets Elasticsearch extract file attachments in common formats (such as PPT, XLS, and PDF) by
  4. using the Apache text extraction library https://tika.apache.org/[Tika].
  5. You can use the ingest attachment plugin as a replacement for the mapper attachment plugin.
  6. The source field must be a base64 encoded binary. If you do not want to incur
  7. the overhead of converting back and forth between base64, you can use the CBOR
  8. format instead of JSON and specify the field as a bytes array instead of a string
  9. representation. The processor will skip the base64 decoding then.
  10. :plugin_name: ingest-attachment
  11. include::install_remove.asciidoc[]
  12. [[using-ingest-attachment]]
  13. ==== Using the Attachment Processor in a Pipeline
  14. [[ingest-attachment-options]]
  15. .Attachment options
  16. [options="header"]
  17. |======
  18. | Name | Required | Default | Description
  19. | `field` | yes | - | The field to get the base64 encoded field from
  20. | `target_field` | no | attachment | The field that will hold the attachment information
  21. | `indexed_chars` | no | 100000 | The number of chars being used for extraction to prevent huge fields. Use `-1` for no limit.
  22. | `indexed_chars_field` | no | `null` | Field name from which you can overwrite the number of chars being used for extraction. See `indexed_chars`.
  23. | `properties` | no | all properties | Array of properties to select to be stored. Can be `content`, `title`, `name`, `author`, `keywords`, `date`, `content_type`, `content_length`, `language`
  24. | `ignore_missing` | no | `false` | If `true` and `field` does not exist, the processor quietly exits without modifying the document
  25. | `remove_binary` | no | `false` | If `true`, the binary `field` will be removed from the document
  26. | `resource_name` | no | | Field containing the name of the resource to decode. If specified, the processor passes this resource name to the underlying Tika library to enable https://tika.apache.org/1.24.1/detection.html#Resource_Name_Based_Detection[Resource Name Based Detection].
  27. |======
  28. [discrete]
  29. [[ingest-attachment-json-ex]]
  30. ==== Example
  31. If attaching files to JSON documents, you must first encode the file as a base64
  32. string. On Unix-like systems, you can do this using a `base64` command:
  33. [source,shell]
  34. ----
  35. base64 -in myfile.rtf
  36. ----
  37. The command returns the base64-encoded string for the file. The following base64
  38. string is for an `.rtf` file containing the text `Lorem ipsum dolor sit amet`:
  39. `e1xydGYxXGFuc2kNCkxvcmVtIGlwc3VtIGRvbG9yIHNpdCBhbWV0DQpccGFyIH0=`.
  40. Use an attachment processor to decode the string and extract the file's
  41. properties:
  42. [source,console]
  43. ----
  44. PUT _ingest/pipeline/attachment
  45. {
  46. "description" : "Extract attachment information",
  47. "processors" : [
  48. {
  49. "attachment" : {
  50. "field" : "data"
  51. }
  52. }
  53. ]
  54. }
  55. PUT my-index-000001/_doc/my_id?pipeline=attachment
  56. {
  57. "data": "e1xydGYxXGFuc2kNCkxvcmVtIGlwc3VtIGRvbG9yIHNpdCBhbWV0DQpccGFyIH0="
  58. }
  59. GET my-index-000001/_doc/my_id
  60. ----
  61. The document's `attachment` object contains extracted properties for the file:
  62. [source,console-result]
  63. ----
  64. {
  65. "found": true,
  66. "_index": "my-index-000001",
  67. "_id": "my_id",
  68. "_version": 1,
  69. "_seq_no": 22,
  70. "_primary_term": 1,
  71. "_source": {
  72. "data": "e1xydGYxXGFuc2kNCkxvcmVtIGlwc3VtIGRvbG9yIHNpdCBhbWV0DQpccGFyIH0=",
  73. "attachment": {
  74. "content_type": "application/rtf",
  75. "language": "ro",
  76. "content": "Lorem ipsum dolor sit amet",
  77. "content_length": 28
  78. }
  79. }
  80. }
  81. ----
  82. // TESTRESPONSE[s/"_seq_no": \d+/"_seq_no" : $body._seq_no/ s/"_primary_term" : 1/"_primary_term" : $body._primary_term/]
  83. NOTE: Keeping the binary as a field within the document might consume a lot of resources. It is highly recommended
  84. to remove that field from the document. Set `remove_binary` to `true` to automatically remove the field.
  85. To extract only certain `attachment` fields, specify the `properties` array:
  86. [source,console]
  87. ----
  88. PUT _ingest/pipeline/attachment
  89. {
  90. "description" : "Extract attachment information",
  91. "processors" : [
  92. {
  93. "attachment" : {
  94. "field" : "data",
  95. "properties": [ "content", "title" ]
  96. }
  97. }
  98. ]
  99. }
  100. ----
  101. NOTE: Extracting contents from binary data is a resource intensive operation and
  102. consumes a lot of resources. It is highly recommended to run pipelines
  103. using this processor in a dedicated ingest node.
  104. [[ingest-attachment-cbor]]
  105. ==== Use the attachment processor with CBOR
  106. To avoid encoding and decoding JSON to base64, you can instead pass CBOR data to
  107. the attachment processor. For example, the following request creates the
  108. `cbor-attachment` pipeline, which uses the attachment processor.
  109. [source,console]
  110. ----
  111. PUT _ingest/pipeline/cbor-attachment
  112. {
  113. "description" : "Extract attachment information",
  114. "processors" : [
  115. {
  116. "attachment" : {
  117. "field" : "data"
  118. }
  119. }
  120. ]
  121. }
  122. ----
  123. The following Python script passes CBOR data to an HTTP indexing request that
  124. includes the `cbor-attachment` pipeline. The HTTP request headers use a
  125. `content-type` of `application/cbor`.
  126. NOTE: Not all {es} clients support custom HTTP request headers.
  127. [source,python]
  128. ----
  129. import cbor2
  130. import requests
  131. file = 'my-file'
  132. headers = {'content-type': 'application/cbor'}
  133. with open(file, 'rb') as f:
  134. doc = {
  135. 'data': f.read()
  136. }
  137. requests.put(
  138. 'http://localhost:9200/my-index-000001/_doc/my_id?pipeline=cbor-attachment',
  139. data=cbor2.dumps(doc),
  140. headers=headers
  141. )
  142. ----
  143. [[ingest-attachment-extracted-chars]]
  144. ==== Limit the number of extracted chars
  145. To prevent extracting too many chars and overload the node memory, the number of chars being used for extraction
  146. is limited by default to `100000`. You can change this value by setting `indexed_chars`. Use `-1` for no limit but
  147. ensure when setting this that your node will have enough HEAP to extract the content of very big documents.
  148. You can also define this limit per document by extracting from a given field the limit to set. If the document
  149. has that field, it will overwrite the `indexed_chars` setting. To set this field, define the `indexed_chars_field`
  150. setting.
  151. For example:
  152. [source,console]
  153. --------------------------------------------------
  154. PUT _ingest/pipeline/attachment
  155. {
  156. "description" : "Extract attachment information",
  157. "processors" : [
  158. {
  159. "attachment" : {
  160. "field" : "data",
  161. "indexed_chars" : 11,
  162. "indexed_chars_field" : "max_size"
  163. }
  164. }
  165. ]
  166. }
  167. PUT my-index-000001/_doc/my_id?pipeline=attachment
  168. {
  169. "data": "e1xydGYxXGFuc2kNCkxvcmVtIGlwc3VtIGRvbG9yIHNpdCBhbWV0DQpccGFyIH0="
  170. }
  171. GET my-index-000001/_doc/my_id
  172. --------------------------------------------------
  173. Returns this:
  174. [source,console-result]
  175. --------------------------------------------------
  176. {
  177. "found": true,
  178. "_index": "my-index-000001",
  179. "_id": "my_id",
  180. "_version": 1,
  181. "_seq_no": 35,
  182. "_primary_term": 1,
  183. "_source": {
  184. "data": "e1xydGYxXGFuc2kNCkxvcmVtIGlwc3VtIGRvbG9yIHNpdCBhbWV0DQpccGFyIH0=",
  185. "attachment": {
  186. "content_type": "application/rtf",
  187. "language": "sl",
  188. "content": "Lorem ipsum",
  189. "content_length": 11
  190. }
  191. }
  192. }
  193. --------------------------------------------------
  194. // TESTRESPONSE[s/"_seq_no": \d+/"_seq_no" : $body._seq_no/ s/"_primary_term" : 1/"_primary_term" : $body._primary_term/]
  195. [source,console]
  196. --------------------------------------------------
  197. PUT _ingest/pipeline/attachment
  198. {
  199. "description" : "Extract attachment information",
  200. "processors" : [
  201. {
  202. "attachment" : {
  203. "field" : "data",
  204. "indexed_chars" : 11,
  205. "indexed_chars_field" : "max_size"
  206. }
  207. }
  208. ]
  209. }
  210. PUT my-index-000001/_doc/my_id_2?pipeline=attachment
  211. {
  212. "data": "e1xydGYxXGFuc2kNCkxvcmVtIGlwc3VtIGRvbG9yIHNpdCBhbWV0DQpccGFyIH0=",
  213. "max_size": 5
  214. }
  215. GET my-index-000001/_doc/my_id_2
  216. --------------------------------------------------
  217. Returns this:
  218. [source,console-result]
  219. --------------------------------------------------
  220. {
  221. "found": true,
  222. "_index": "my-index-000001",
  223. "_id": "my_id_2",
  224. "_version": 1,
  225. "_seq_no": 40,
  226. "_primary_term": 1,
  227. "_source": {
  228. "data": "e1xydGYxXGFuc2kNCkxvcmVtIGlwc3VtIGRvbG9yIHNpdCBhbWV0DQpccGFyIH0=",
  229. "max_size": 5,
  230. "attachment": {
  231. "content_type": "application/rtf",
  232. "language": "ro",
  233. "content": "Lorem",
  234. "content_length": 5
  235. }
  236. }
  237. }
  238. --------------------------------------------------
  239. // TESTRESPONSE[s/"_seq_no": \d+/"_seq_no" : $body._seq_no/ s/"_primary_term" : 1/"_primary_term" : $body._primary_term/]
  240. [[ingest-attachment-with-arrays]]
  241. ==== Using the Attachment Processor with arrays
  242. To use the attachment processor within an array of attachments the
  243. {ref}/foreach-processor.html[foreach processor] is required. This
  244. enables the attachment processor to be run on the individual elements
  245. of the array.
  246. For example, given the following source:
  247. [source,js]
  248. --------------------------------------------------
  249. {
  250. "attachments" : [
  251. {
  252. "filename" : "ipsum.txt",
  253. "data" : "dGhpcyBpcwpqdXN0IHNvbWUgdGV4dAo="
  254. },
  255. {
  256. "filename" : "test.txt",
  257. "data" : "VGhpcyBpcyBhIHRlc3QK"
  258. }
  259. ]
  260. }
  261. --------------------------------------------------
  262. // NOTCONSOLE
  263. In this case, we want to process the data field in each element
  264. of the attachments field and insert
  265. the properties into the document so the following `foreach`
  266. processor is used:
  267. [source,console]
  268. --------------------------------------------------
  269. PUT _ingest/pipeline/attachment
  270. {
  271. "description" : "Extract attachment information from arrays",
  272. "processors" : [
  273. {
  274. "foreach": {
  275. "field": "attachments",
  276. "processor": {
  277. "attachment": {
  278. "target_field": "_ingest._value.attachment",
  279. "field": "_ingest._value.data"
  280. }
  281. }
  282. }
  283. }
  284. ]
  285. }
  286. PUT my-index-000001/_doc/my_id?pipeline=attachment
  287. {
  288. "attachments" : [
  289. {
  290. "filename" : "ipsum.txt",
  291. "data" : "dGhpcyBpcwpqdXN0IHNvbWUgdGV4dAo="
  292. },
  293. {
  294. "filename" : "test.txt",
  295. "data" : "VGhpcyBpcyBhIHRlc3QK"
  296. }
  297. ]
  298. }
  299. GET my-index-000001/_doc/my_id
  300. --------------------------------------------------
  301. Returns this:
  302. [source,console-result]
  303. --------------------------------------------------
  304. {
  305. "_index" : "my-index-000001",
  306. "_id" : "my_id",
  307. "_version" : 1,
  308. "_seq_no" : 50,
  309. "_primary_term" : 1,
  310. "found" : true,
  311. "_source" : {
  312. "attachments" : [
  313. {
  314. "filename" : "ipsum.txt",
  315. "data" : "dGhpcyBpcwpqdXN0IHNvbWUgdGV4dAo=",
  316. "attachment" : {
  317. "content_type" : "text/plain; charset=ISO-8859-1",
  318. "language" : "en",
  319. "content" : "this is\njust some text",
  320. "content_length" : 24
  321. }
  322. },
  323. {
  324. "filename" : "test.txt",
  325. "data" : "VGhpcyBpcyBhIHRlc3QK",
  326. "attachment" : {
  327. "content_type" : "text/plain; charset=ISO-8859-1",
  328. "language" : "en",
  329. "content" : "This is a test",
  330. "content_length" : 16
  331. }
  332. }
  333. ]
  334. }
  335. }
  336. --------------------------------------------------
  337. // TESTRESPONSE[s/"_seq_no" : \d+/"_seq_no" : $body._seq_no/ s/"_primary_term" : 1/"_primary_term" : $body._primary_term/]
  338. Note that the `target_field` needs to be set, otherwise the
  339. default value is used which is a top level field `attachment`. The
  340. properties on this top level field will contain the value of the
  341. first attachment only. However, by specifying the
  342. `target_field` on to a value on `_ingest._value` it will correctly
  343. associate the properties with the correct attachment.