我发现在NiFi中无法直接从Avro中提取属性,所以我使用的是ConvertAvroToJson - > EvaluateJsonPath - > ConvertJsonToAvro作为解决方法。
但我想编写一个脚本来从Avro流文件中提取属性,以便在ExecuteScript处理器中使用,以确定它是否是更好的方法。
有没有人有脚本来执行此操作?否则,我最终可能会使用原始方法。
谢谢,
凯文
答案 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元数据。