我想我有一个产生两个输出的函数(如果我错了,请纠正我):
PCollection<String> words = ...;
final TupleTag<String> shortWordsTag = new TupleTag<String>(){};
PCollectionTuple results =
words.apply(
ParDo
.of(new DoFn<String, String>() {
@ProcessElement
public void processElement(ProcessContext context) {
String word = context.element();
if (word.length() < 5) {
context.output(shortWordsTag, word);
} else {
context.output(word);
}
现在,我想调用另一个函数,但仅将其应用到这些输出之一。像这样:
results.apply(
ParDo
.of(new DoFn<String, String>() {
@ProcessElement
public void processElement(ProcessContext context) {
String word = context.element();
// do stuff, but should only have words with length < 5 here
}
)
我可以看到一些使用withOutputTags
的示例,但是这种方法似乎采用了多个标签(一个标签和一系列标签),而且我不确定如何在我的场景中使用它。
如何指定我的results.apply
仅用于输出到shortWordsTag
标签的数据?
答案 0 :(得分:1)
如前所述,在Apache Beam中通过单个转换处理多个输出的正确方法确实是使用from contextvars import ContextVar
# ...
in_queue = ContextVar('in_queue')
out_queue = ContextVar('out_queue')
async def run():
in_, out = asyncio.Queue(), asyncio.Queue()
in_queue.set(in_)
out_queue.set(out)
for request in range(1):
await in_.put(request)
# ...
for i in range(num_workers):
tasks.append(asyncio.create_task(worker(name=f'worker-{i}')))
tasks.append(asyncio.create_task(saver()))
await in_.join()
await out.join()
# ...
async def worker(name):
print(f"{name} started")
in_ = in_queue.get()
out = out_queue.get()
try:
while True:
num = await in_.get()
try:
# ...
await out.put(num)
# ...
finally:
in_.task_done()
# ...
async def saver():
print("saver started")
out = out_queue.get()
try:
while True:
num = await out.get()
try:
# ...
finally:
out.task_done()
# ...
和PCollectionTuple
。
在Apache Beam文档中,您可以找到一些非常好的示例,这些示例关于如何使用多个输出为每个输出使用不同的标记来设置转换:
此外,如果您访问上面第二个链接中的4.5.2节,您将找到有关如何向DoFn中的多个输出发出信号的示例。简而言之,使用共享的核心代码,您需要执行以下操作:
withOutputTags
调用get( )
method on a PCollectionTuple将返回与将在方法内部传递的TupleTag关联的PCollection。