我希望能够通过自定义键使用分组,但是到目前为止,这是我的尝试,
我们将自定义类用于KV对象的键,因为我们希望GroupBy具有更复杂的条件,而不是使用String等进行简单的键匹配。
```
PCollection<KV<Multikey, Iterable<SomeObject>> pc2 =
pc.apply(GroupByKey.<Multikey, SomeObject>create());
```
使用equals方法表达匹配条件。
```
class Multikey implements Serializable{
List<String> keys = new ArrayList<>(); //multiple key
......
@Override
public boolean equals(Object k){
...join conditions
}
}
```
但是我得到一个错误。
java.lang.IllegalStateException: the keyCoder of a GroupByKey must be deterministic
at org.apache.beam.sdk.transforms.GroupByKey.expand(GroupByKey.java:193)
at org.apache.beam.sdk.transforms.GroupByKey.expand(GroupByKey.java:107)
at org.apache.beam.sdk.Pipeline.applyInternal(Pipeline.java:537)
at org.apache.beam.sdk.Pipeline.applyTransform(Pipeline.java:471)
at org.apache.beam.sdk.values.PCollection.apply(PCollection.java:357)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:282)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.beam.sdk.coders.Coder$NonDeterministicException: org.apache.beam.sdk.coders.SerializableCoder@18b411b5 is not deterministic because:
Java Serialization may be non-deterministic.
at org.apache.beam.sdk.coders.SerializableCoder.verifyDeterministic(SerializableCoder.java:205)
at org.apache.beam.sdk.transforms.GroupByKey.expand(GroupByKey.java:191)
似乎“键”的序列化顺序是错误的,因此我实现了自定义序列化器或尝试了各种编码器,但是没有用。
答案 0 :(得分:1)
不通过常规Java Object.equals(java.lang.Object)比较K类型的两个键是否相等,而是首先使用输入PCollection的键的Coder编码每个键,然后进行比较编码的字节。这承认了有效的并行评估。请注意,这要求键的编码器是确定性的(请参阅Coder.verifyDeterministic())。如果关键编码器不确定,则在管道构建时将引发异常。
一种可能的方法:根据您提到的复杂的条件逻辑,使用一个输出KV的pardo,使用唯一键作为字符串输出值。
另一种方法是使用自定义对象类型作为键,而不是字符串,就像您到目前为止已经尝试过的那样。您将需要实现一个CustomCoder,它相当于代表相同密钥的两个对象的字节大小。
这是specifying coders上的Apache Beam文档。
这是一篇博客文章,其中包含一些自定义编码器examples as well。
此外,Re:异常本身。请参阅verifyDeterministic文档,以查看description of a deterministic coder。您很可能违反了此约束。
答案 1 :(得分:0)
谢谢。我读了文件。
我将解释为什么要使用自定义键。
那是因为我们要表达“或”之类的析取语,而不是常规组合。
class Multikey implements Serializable
List <String> keys = new ArrayList <> ();
........
@Override
public boolean equals (Object k) {
if (k instanceof Multikey) {
List <String> ky = new ArrayList <String> (((Multikey) k) .keys);
// Representation of disjunction
ky.retainAll (keys);
return! ky.isEmpty ();
} else {
return false;
}
}
我阅读了文档,但是似乎GroupBy的密钥需要是一个确定性值。 在分组中难于表达分离吗?