Google数据流:写入数据存储区而不覆盖现有实体

时间:2017-06-09 15:54:52

标签: java google-cloud-datastore google-cloud-dataflow apache-beam

TLDR:寻找一种更新数据存储区实体的方法,而不会通过Dataflow覆盖现有数据

我正在使用dataflow 2.0.0(beam)更新Google Datastore中的实体。我的数据流从数据存储区加载实体,更新它们,然后将它们保存回数据存储区(覆盖现有实体)。

但是,在更新过程中,我还会发现可能已存在或可能尚未存在的其他实体。为了防止覆盖现有实体,我以前会从数据存储区加载所有实体并减少它们(逐个组),删除新的重复项。

随着实体数量的增长,我希望避免必须将所有实体加载到Dataflow中(而是根据最旧的时间戳批量生成),但我遇到的问题是旧实体在被覆盖时会被覆盖不在当前批次中。

我正在使用(在两个位置,一个用于现有实体,一个用于新实体)将实体写入Dataflow:

collection.apply(DatastoreIO.v1().write().withProjectId("..."))

如果有类似DatastoreIO.v1().writeNew()方法的东西会很好,但遗憾的是它不存在。谢谢你的帮助。

1 个答案:

答案 0 :(得分:1)

如果要编写数据存储区中不存在的新实体,只需使用新密钥创建一个并写入即可。

List<String> keyNames = Arrays.asList("L1", "L2"); // Somewhat you have new keys to store
PTransform<PCollection<Entity>, ?> write =
        DatastoreIO.v1().write().withProjectId(project_id); // This is a typical write operation

p.
    apply("GetInMemory", Create.of(keyNames)).setCoder(StringUtf8Coder.of()). // L1 and L2 are loaded
    apply("Proc1", ParDo.of(new DoFn<String, Entity>(){
        @ProcessElement
        public void processElement(ProcessContext c) {
            Key.Builder key = makeKey("k2", c.element());  // Generate an entity key
            final Entity entity = Entity.newBuilder().
                    setKey(key). // Set the key
                    putProperties("p1", makeValue(new String("test constant value")
                        ).setExcludeFromIndexes(true).build()).
                    build();
            c.output(entity);
        }
    })).
    apply(write); // Write them
p.run();

可以在https://github.com/yiu31802/gcp-project/commit/cc224b34

的代码库中引用整个代码