需要使用NiFi直接从Avro中提取属性

时间:2017-08-02 17:59:21

标签: apache-nifi

我发现在NiFi中无法直接从Avro中提取属性,所以我使用的是ConvertAvroToJson - > EvaluateJsonPath - > ConvertJsonToAvro作为解决方法。

但我想编写一个脚本来从Avro流文件中提取属性,以便在ExecuteScript处理器中使用,以确定它是否是更好的方法。

有没有人有脚本来执行此操作?否则,我最终可能会使用原始方法。

谢谢,

凯文

2 个答案:

答案 0 :(得分:1)

这是一个Groovy脚本(需要在其模块目录属性中使用Avro JAR),我让用户指定动态属性,并根据Avro文件评估JSONPath表达式。具有讽刺意味的是,无论如何它都会将GenericData.toString()转换为JSON,但也许这里有一些代码可以重用:

import org.apache.avro.*
import org.apache.avro.generic.*
import org.apache.avro.file.*
import groovy.json.*
import org.apache.commons.io.IOUtils
import java.nio.charset.*

flowFile = session.get()
if(!flowFile) return

final GenericData genericData = GenericData.get();
slurper = new JsonSlurper().setType(JsonParserType.INDEX_OVERLAY)

pathAttrs = this.binding?.variables?.findAll {attr -> attr.key.startsWith('avro.path')}
newAttrs = [:]
try {
   session.read(flowFile, { inputStream ->
   def reader = new DataFileStream<>(inputStream, new GenericDatumReader<GenericRecord>())
   GenericRecord currRecord = null;
   if(reader.hasNext()) {
       currRecord = reader.next();
       log.info(genericData.toString(currRecord))
       record = slurper.parseText(genericData.toString(currRecord))
       pathAttrs?.each {k,v ->
         object = record
         v.value.tokenize('.').each {
            object = object[it]
          }
          newAttrs[k - "avro.path."] = String.valueOf(object)
        }
        reader.close()
   }
} as InputStreamCallback)
newAttrs.each{k,v ->
  flowFile = session.putAttribute(flowFile, k,v)
}
session.transfer(flowFile, REL_SUCCESS)
} catch(e) {
  log.error("Error during Avro Path: {}", [e.message] as Object[], e)
  session.transfer(flowFile, REL_FAILURE)
}

如果你想提取Avro元数据vs字段(不完全确定你的意思是什么&#34;属性&#34;),还要检查MergeContent&#39; s AvroMerge,因为那里有一些代码拉Avro元数据:

答案 1 :(得分:0)

如果要从每个流文件的单个Avro记录中提取简单模式,ExtractText可能就足够了。如果您想利用Apache NiFi 1.3.0中提供的新记录处理,AvroReader就是您应该开始的地方,a series blogs描述了此process } 详细地。您还可以使用ExtractAvroMetadata提取Avro元数据。