【问题标题】:NiFi – How can I use MergeRecord to Merge Files into JSON WITHOUT Producing JSON Array?NiFi – 如何使用 MergeRecord 将文件合并到 JSON 中而不生成 JSON 数组?
【发布时间】:2019-04-22 18:11:44
【问题描述】:

我有两个 XML 文件(下面的虚拟版本,实际包含 PII),我正在尝试使用 MergeRecord 将它们合并到一个流文件中。我的流程是获取文件,我使用 ExtractText 提取 FatherID/DOCID 并将其添加为属性,然后在 MergeRecord 配置中使用它。我的 MergeRecord 配置包括一个 XML 读取器、一个 JSON 写入器和一个 Avro 模式,我已粘贴在下面。

但是,我的输出是一个包含 JSON 数组的流文件,而不是一个 JSON。这是一个问题,因为我将把它放入 Elasticsearch,如果我将一个流文件放入 Elasticsearch,它会将其视为两个单独的条目。我听说过一些关于使用 JoltTransform 的建议,但我什至不知道从哪里开始。

输入 XML 1

<?xml version="1.0" encoding="UTF-8"?>
<FoundingFathers>
   <FatherID>1234</FatherID>
   <FatherName>George Washington</FatherName>
   <ResidentialInformation>
      <Name>Mount Vernon</Name>
      <StreetAddress>3200 Mount Vernon Hwy</StreetAddress>
       <City>Mt Vernon</City>
       <State>VA</State>
       <ZipCode>22121</ZipCode>
   </ResidentialInformation>
    <BirthDate>1732-02-22</BirthDate>
</FoundingFathers>

输入 XML 2

<?xml version="1.0" encoding="UTF-8"?>
<DOC>
   <DOCID>1234</DOCID>
   <FATHERNAME>George Washington</FATHERNAME>
   <RAW_TXT>George Washington lived in Mount Vernon in Mt Vernon, VA. The Washington family had owned land in the area since 1674. The original house was built in 1734 by Washington's father.</RAW_TXT>
   <TXT>
      <S>
         <FATHERNAME>George Washington</FATHERNAME>
         <ESTATENAME>Mount Vernon</>
         <ESTATEPLACE>VA</ESTATEPLACE>
      </S>
      <S>
         <OWNER>Washington family</OWNER>
         <YEAROWNED>1674</YEAROWNED>
      </S>
      <S>
         <BUILTIN>1734</BUILTIN>
         <BUILTBY>Washington's father</BUILTBY>
      </S>
   </TXT>
</DOC>

MergeRecord 配置

Record Reader: XMLReader
Record Writer: JsonRecordSetWriter
Merge Strategy: Bin-Packing Algorithm
Correlation Attribute Name: FatherID
Attribute Strategy: Keep All Unique Attributes
Minimum Number of Records: 2
Maximum Number of Records: 2
Minimum Bin Size: 0 B
Maximum Bin Size: No value set
Max Bin Age: No value set
Maximum Number of Bins: 10

架构

{
  "namespace": "ff",
  "name": "founders",
  "type": "record",
  "fields": [
    {"name":"FatherID", "type": ["string", "null"], "default": null},
    {"name":"FatherName", "type": ["string", "null"], "default": null},
    {"name":"ResidentialInformation", "type": ["null", {
      "name": "ResidentialInformation", "type": "array", "items": {
        "name": "ResidentialInformation", "type": "record", "fields": [
          {"name": "Name", "type": ["string","null"], "default":null},
          {"name": "StreetAddress", "type": ["string","null"], "default":null},
          {"name": "City", "type": ["string","null"], "default":null},
          {"name": "State", "type": ["string","null"], "default":null},
          {"name": "ZipCode", "type": ["string","null"], "default":null}
        ]
      }
    }]},
    {"name":"BirthDate", "type": ["string", "null"], "default": null},
    {"name": "DOCID", "type": ["string", "null"], "default": null},
    {"name": "FINAME", "type": ["string", "null"], "default": null},
    {"name": "CUSTNAME", "type": {"type": "array", "items": "string"}},
    {"name": "RAW_TXT", "type": {"type": "array", "items": "string"}},
    {"name": "TXT", "type": {
      "name": "TXT", "type": "record", "namespace": "txt.sar", "fields": [
        {"name": "S", "type": {
          "type": "array", "items": {
            "name": "RecordInArray", "type": "record", "fields": [
              {"name": "FATHERNAME", "type": {"type": "array", "items": ["string","null"]}},
              {"name": "ESTATENAME", "type": {"type": "array", "items": ["string","null"]}},
              {"name": "ESTATEPLACE", "type": {"type": "array", "items": ["string","null"]}},
              {"name": "OWNER", "type": {"type": "array", "items": ["string","null"]}},
              {"name": "YEAROWNED", "type": {"type": "array", "items": ["string","null"]}},
              {"name": "BUILTIN", "type": {"type": "array", "items": ["string","null"]}},
              {"name": "BUILTBY", "type": {"type": "array", "items": ["string","null"]}}
            ]
          }
        }}
      ]
    }}
  ]}

实际输出

[ {
  "FatherID" : "1234",
  "FatherName" : "George Washington",
  "ResidentialInformation" : [ {
    "Name" : "Mount Vernon",
    "StreetAddress" : "3200 Mount Vernon Hwy",
    "City" : "Mt Vernon",
    "State" : "VA",
    "ZipCode" : "22121"
  } ],
  "BirthDate" : "1732-02-22",
  "DOCID" : null,
  "FATHERNAME" : null,
  "RAW_TXT" : [ ],
  "TXT" : null
}, {
  "FatherID" : null,
  "FatherName" : null,
  "BirthDate" : null,
  "DOCID" : "1234",
  "FATHERNAME" : "George Washington",
  "RAW_TXT" : [ "\nGeorge Washington lived in Mount Vernon in Mt Vernon, VA. The Washington family had owned land in the area since 1674. The original house was built in 1734 by Washington's father.\n" ],
  "TXT" : {
    "S" : [ {
      "FATHERNAME" : [ "George Washington" ],
      "ESTATENAME" : [ "Mount Vernon" ],
      "ESTATEPLACE" : [ "VA" ]
    }, {
      "OWNER" : [ "Washington family" ],
      "YEAROWNED" : [ "1674" ]
    }, {
      "BUILTIN" : [ "1734" ],
      "BUILTBY" : [ "Washington's father" ]
    } ]
  }
} ]

预期输出

[ {
  "FatherID" : "1234",
  "FatherName" : "George Washington",
  "ResidentialInformation" : [ {
    "Name" : "Mount Vernon",
    "StreetAddress" : "3200 Mount Vernon Hwy",
    "City" : "Mt Vernon",
    "State" : "VA",
    "ZipCode" : "22121"
  } ],
  "BirthDate" : "1732-02-22",
  "DOCID" : "1234",
  "FATHERNAME" : "George Washington",
  "RAW_TXT" : [ "\nGeorge Washington lived in Mount Vernon in Mt Vernon, VA. The Washington family had owned land in the area since 1674. The original house was built in 1734 by Washington's father.\n" ],
  "TXT" : {
    "S" : [ {
      "FATHERNAME" : [ "George Washington" ],
      "ESTATENAME" : [ "Mount Vernon" ],
      "ESTATEPLACE" : [ "VA" ]
    }, {
      "OWNER" : [ "Washington family" ],
      "YEAROWNED" : [ "1674" ]
    }, {
      "BUILTIN" : [ "1734" ],
      "BUILTBY" : [ "Washington's father" ]
    } ]
  }
} ]

【问题讨论】:

    标签: json xml apache-nifi jolt


    【解决方案1】:

    所需的输出更多的是连接,而不是合并。合并只是一个接一个地放置记录或内容,在这种情况下创建一个 json 数组,其中数组中的每个条目是属于合并的每个流文件的 json。

    处理器并不真正进行真正的流式连接,但此答案中描述了一种可用于连接两个 JSON 流文件的方法:

    https://stackoverflow.com/a/55124212/5650316

    【讨论】:

    • 它工作得很好,但是,它把FatherID变成了一个数组(“FatherID”:[“1234”,null])——知道是什么原因造成的吗?
    • 我对 JOLT 的了解并不多,但我认为并不是真的希望您拥有名称相同但值不同的字段。我认为如果两者中的 FatherId 都是 1234,那么它可能不会创建数组,或者如果只有一个文档的 FatherId 为 1234 而 null 不存在,那么它可能不会产生数组。
    • 对不起,我没有写清楚的评论。它将每个字段(住宅信息下的嵌套值除外)都制成一个数组。即 "FatherID" : ["1234", null], "FatherName" : ["George Washington", null] 等等
    • 好吧,当有重叠的字段名称时,它可能不起作用。. JOLT 试图将每条记录中的字段名称合并为一个,当它看到一个字段两次时,它不知道该怎么做,所以它代表数组中的值。
    • 有更多 JOLT 经验的人可能知道是否有更好的方法。您始终可以回退到自定义处理器或脚本处理器,它们可以更具体地处理您的数据并执行您需要执行的任何操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多