在Apache Crunch中是否存在将PCollection转换为PTable的通用方法?

时间:2017-08-14 08:29:24

标签: apache-crunch

我在util类中有这些方法,它们将特定的PCollection转换为特定的PTable。

public static PTable<IdDetails, CASegmentsForModification> getPTableForCASegments(PCollection<CASegmentsForModification> aggregatedPCollectionForCASegments) {
    return aggregatedPCollectionForCASegments.parallelDo(new CASegmentsPTableConverter(),
            Avros.tableOf(Avros.records(IdDetails.class), Avros.records(CASegmentsForModification.class)));
}

public static PTable<IdDetails, UserPrimaryIdMapping> getPTableForPrimaryIdMapping(PCollection<UserPrimaryIdMapping> pCollectionOfUserPrimaryIdMapping) {
    return pCollectionOfUserPrimaryIdMapping.parallelDo(new UserPrimaryIdMappingPTableConverter(),
            Avros.tableOf(Avros.records(IdDetails.class), Avros.records(UserPrimaryIdMapping.class)));
}

public static PTable<IdDetails, UserGroupSegments> getPTableForUserGroupSegments(PCollection<UserGroupSegments> pCollectionOfUserGroupSegments) {
    return pCollectionOfUserGroupSegments.parallelDo(new UserGroupSegmentsPTableConverter(),
            Avros.tableOf(Avros.records(IdDetails.class), Avros.records(UserGroupSegments.class)));
}

如何实现上述方法的一种通用方法?

2 个答案:

答案 0 :(得分:2)

有一种更好的方法可以使用PTables util类中的静态asPtable方法。您的PCollection必须是Pair类型,PTable结果将是PTable类型

    public static <K,V> PTable<K,V> asPTable(PCollection<Pair<K,V>> pcollect)

根据您的示例,您只需创建DoFn(或扩展类)即可返回Avros.pairs(Avros.records(yourClass.class),Avros.records(yourOtherClass.class))。

另一种方法是使用预定义的MapFn ExtractKEyFn并将其应用于您的集合。您需要实现map方法来提取密钥并生成密钥值输出。它基本上是相同的想法,之后你可以转换PCollection&gt;进入PTable

它应该为您节省大量的样板代码。

以防万一,还有其他功能可能有用FilterFn,但是当您使用MemPipeline进行单元测试时,我们发现了一些错误。我建议的第一种方法应该是最安全的。

编辑:

保存一些代码的良好平衡是使用字段名称根据字段名称获取密钥,并为每个PCollection调用此MapFn。

//we are assuming the key will be in the first level of your record
public class GenericRecordToPair <V extends GenericRecord, K extends GenericRecord> extends MapFn<V, Pair<K, V>> {
    String key;

    public GenericRecordToPair(String key){
        this.key = key;
    }

    @Override
    public Pair<T, TupleN> map(S input) {
        return new Pair<K,V> (input.get(key), input);
    }

}

从您的示例中,您可以执行类似

的操作
PCollection<UserGroupSegments> pCollectionOfUserGroupSegments = ...//comming from somewhere
PCollection<UserPrimaryIdMapping> pCollectionOfUserPrimaryIdMapping = ...//comming from somewhere
PTable<IdDetails, UserGroupSegments> pTable1 = PTables.asPTable(pCollectionOfUserGroupSegments.parallelDo(new GenericRecordToPair("idDetails"), Avros.pairs(Avros.records(IdDetails.class), Avros.records(UserGroupSegments))));
PTable<IdDetails, UserPrimaryIdMapping> pTable2 = PTables.asPTable(pCollectionOfUserPrimaryIdMapping.parallelDo(new GenericRecordToPair("idDetails"), Avros.pairs(Avros.records(IdDetails.class), Avros.records(UserPrimaryIdMapping))));

答案 1 :(得分:0)

这正是PCollection.by方法的目的,它接受MapFn生成密钥并返回一个PTable,每个记录由该MapFn的结果键入。

所以你可以这样做:

PTable<IdDetails, CASegmentsForModification> pTableForCASegments = aggregatedPCollectionForCASegments.by(
    new CASegmentsKeyMapFn(),
    Avros.records(IdDetails.class)
)