Google cloud dataflow 用于在数据流中分组的自定义键

Google cloud dataflow 用于在数据流中分组的自定义键,google-cloud-dataflow,apache-beam,Google Cloud Dataflow,Apache Beam,我希望能够通过自定义键使用分组,但这是我迄今为止的尝试 我们对KV对象的键使用自定义类,因为我们希望使用更复杂的条件分组,而不是使用字符串等简单的键匹配 ``` PCollection<KV<Multikey, Iterable<SomeObject>> pc2 = pc.apply(GroupByKey.<Multikey, SomeObject>create()); ``` 似乎“键”序列化的顺序是错误的,所以我实现了一个自定

我希望能够通过自定义键使用分组,但这是我迄今为止的尝试

我们对KV对象的键使用自定义类,因为我们希望使用更复杂的条件分组,而不是使用字符串等简单的键匹配

```

    PCollection<KV<Multikey, Iterable<SomeObject>> pc2 = 
    pc.apply(GroupByKey.<Multikey, SomeObject>create());

```
似乎“键”序列化的顺序是错误的,所以我实现了一个自定义序列化程序或尝试了各种编码器,但都不起作用。

请注意:

不是通过常规的Java Object.equals(Java.lang.Object)来比较K类型的两个键是否相等,而是首先使用输入PCollection键的编码器对每个键进行编码,然后比较编码的字节。这允许进行有效的并行评估。请注意,这要求密钥的编码器是确定性的(请参阅Coder.verifyDeterministic()。如果密钥编码器不是确定性的,则在管道构造时抛出异常

一种可能的方法是:使用输出KVs的pardo,根据您提到的复杂条件逻辑,将具有唯一键的值作为字符串输出

另一种方法是对键使用自定义对象类型,而不是像您目前尝试的那样使用字符串。对于表示同一个键的两个对象,需要实现一个字节等效的

以下是有关的Apache Beam文档

下面是一篇博客文章,其中有一些定制的编码器


另外,Re:例外本身。请参阅verifyDeterministic docs以查看。很可能您违反了此合同。

谢谢。我看了文件

我将解释为什么要使用自定义密钥

这是因为我们想要表达一个像“或”这样的析取,而不是一个正常的组合

    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;
            }
    }
类多键实现可序列化
列表键=新的ArrayList();
........
@覆盖
公共布尔等于(对象k){
if(多键的k实例){
List ky=新的ArrayList(((多键)k).keys);
//析取的表示
ky.Retainal(钥匙);
return!ky.isEmpty();
}其他{
返回false;
            }
    }
我阅读了文档,但GroupBy的键似乎需要是一个确定的值。
在分组中表示析取是否困难?

是的,所有内容都必须分配给一个键。如果要将一个元素分配给多个键,则必须使用单独的键输出该元素两次。
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)
    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;
            }
    }