Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-cloud-platform/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Google cloud platform 如何在使用Google数据流处理数据时报告无效数据?_Google Cloud Platform_Google Cloud Dataflow - Fatal编程技术网

Google cloud platform 如何在使用Google数据流处理数据时报告无效数据?

Google cloud platform 如何在使用Google数据流处理数据时报告无效数据?,google-cloud-platform,google-cloud-dataflow,Google Cloud Platform,Google Cloud Dataflow,我正在查看和,以了解如何在使用Google的处理数据时报告无效数据 除了实际的In-/output之外,我还想生成第二个输出文件,其中包含被视为无效的记录(例如数据丢失、数据格式错误、值过高)。我想对这些记录进行故障排除,并单独处理它们 输入:gs://…/Input.csv 输出:gs://…/Output.csv 无效记录列表:gs://…/invalid.csv 如何将这些无效记录重定向到单独的输出?您可以使用从单个转换返回多个PCollection。比如说, TupleTag<

我正在查看和,以了解如何在使用Google的处理数据时报告无效数据

除了实际的In-/output之外,我还想生成第二个输出文件,其中包含被视为无效的记录(例如数据丢失、数据格式错误、值过高)。我想对这些记录进行故障排除,并单独处理它们

  • 输入:gs://…/Input.csv
  • 输出:gs://…/Output.csv
  • 无效记录列表:gs://…/invalid.csv
如何将这些无效记录重定向到单独的输出?

您可以使用从单个转换返回多个PCollection。比如说,

TupleTag<String> mainOutput = new TupleTag<>("main");
TupleTag<String> missingData = new TupleTag<>("missing");
TupleTag<String> badValues = new TupleTag<>("bad");

Pipeline p = Pipeline.create(options);
PCollectionTuple all = p
   .apply(TextIO.Read.named("ReadMyFile").from(options.getInput()))
   .apply(new SomeTransformation());

all.get(mainOutput)
   .apply(TextIO.Write.named("WriteMyFile").to(options.getOutput()));
all.get(missingData)
   .apply(TextIO.Write.named("WriteMissingData").to(...));
...
TupleTag main输出=新的TupleTag(“main”);
TupleTag missingData=新TupleTag(“缺失”);
TupleTag badValues=新的TupleTag(“坏”);
Pipeline p=Pipeline.create(选项);
PCollectionTuple all=p
.apply(TextIO.Read.named(“ReadMyFile”).from(options.getInput())
.apply(新的SomeTransformation());
all.get(主输出)
.apply(TextIO.Write.named(“WriteMyFile”).to(options.getOutput());
all.get(丢失数据)
.apply(TextIO.Write.named(“WriteMissingData”).to(…);
...
PCollectionTuple可以直接从现有的PCollections中构建,也可以从带有侧输出的ParDo操作中发出,例如

PCollectionTuple partitioned = input.apply(ParDo
    .of(new DoFn<String, String>() {
          public void processElement(ProcessContext c) {
             if (checkOK(c.element()) {
                 // Shows up in partitioned.get(mainOutput).
                 c.output(...);
             } else if (hasMissingData(c.element())) {
                 // Shows up in partitioned.get(missingData).
                 c.sideOutput(missingData, c.element());
             } else {
                 // Shows up in partitioned.get(badValues).
                 c.sideOutput(badValues, c.element());
             }
          }
        })
    .withOutputTags(mainOutput, TupleTagList.of(missingData).and(badValues)));
PCollectionTuple partitioned=input.apply(ParDo
。of(新DoFn(){
公共void processElement(ProcessContext c){
如果(选中OK(c.元素()){
//显示在partitioned.get(mainOutput)中。
c、 产出(……);
}else if(hasMissingData(c.element())){
//显示在partitioned.get(missingData)中。
c、 sideOutput(missingData,c.element());
}否则{
//显示在partitioned.get(badValues)中。
c、 sideOutput(badValues,c.element());
}
}
})
.withOutputTags(main输出,TupleTagList.of(missingData.)和(badValues));
请注意,一般情况下,各种边输出不需要具有相同的类型,并且数据可以多次发送到任意数量的边输出(而不是我们这里的严格分区)

然后,您的SomeTransformation类可以如下所示

class SomeTransformation extends PTransform<PCollection<String>,
                                            PCollectionTuple> {
  public PCollectionTuple apply(PCollection<String> input) {
    // Filter into good and bad data.
    PCollectionTuple partitioned = ...
    // Process the good data.
    PCollection<String> processed =
        partitioned.get(mainOutput)
                   .apply(...)
                   .apply(...)
                   ...;
    // Repackage everything into a new output tuple.
    return PCollectionTuple.of(mainOutput, processed)
                           .and(missingData, partitioned.get(missingData))
                           .and(badValues, partitioned.get(badValues));
  }
}
类SomeTransformation扩展了PTransform{
公共PCollectionTuple应用(PCollection输入){
//过滤好的和坏的数据。
PCollectionTuple分区=。。。
//处理好数据。
PCollection已处理=
partitioned.get(main输出)
.apply(…)
.apply(…)
...;
//将所有内容重新打包到新的输出元组中。
返回PCollectionTuple.of(主输出,已处理)
.和(丢失数据,分区.get(丢失数据))
.和(badValues,partitioned.get(badValues));
}
}

Robert关于使用SideOutput的建议很好,但请注意,只有当您的ParDos识别出坏数据时,这才有效。目前还没有一种方法可以识别在初始解码过程中命中的坏记录(在Coder.decode中命中错误)。我们计划很快解决这一问题

class SomeTransformation extends PTransform<PCollection<String>,
                                            PCollectionTuple> {
  public PCollectionTuple apply(PCollection<String> input) {
    // Filter into good and bad data.
    PCollectionTuple partitioned = ...
    // Process the good data.
    PCollection<String> processed =
        partitioned.get(mainOutput)
                   .apply(...)
                   .apply(...)
                   ...;
    // Repackage everything into a new output tuple.
    return PCollectionTuple.of(mainOutput, processed)
                           .and(missingData, partitioned.get(missingData))
                           .and(badValues, partitioned.get(badValues));
  }
}