我想使用apache Beam将实体向上插入数据存储,但是在执行WriteToDatastore之前,我创建了一个自定义DoFN -从导入步骤中获取实体, -检查实体是否存在于数据存储区中 -如果是,则提取属性的值并将其与新实体连接。 -输出实体
示例:我的数据由以下几列组成:parent_id,国籍和child_name。输入数据是新出生的孩子。在升级到数据存储区之前,我要获取父级的现有儿童并附加新值。
with beam.Pipeline(options=options) as p:
(p | 'Reading input file' >> beam.io.ReadFromText(input_file_path)
| 'Converting from csv to dict' >> beam.ParDo(CSVtoDict())
| 'Create entities' >> beam.ParDo(CreateEntities())
| 'Update entities' >> beam.ParDo(UpdateEntities())
| 'Write entities into Datastore' >> WriteToDatastore(PROJECT)
)
花费最多时间的Pardo是更新实体:
class UpdateEntities(beam.DoFn):
"""Updates Datastore entity"""
def process(self, element):
query = query_pb2.Query()
parent_key = entity_pb2.Key()
parent = datastore_helper.get_value(element.properties['parent_id'])
datastore_helper.add_key_path(parent_key, kind, parent)
parent_key.partition_id.namespace_id = datastore_helper.get_value(element.properties['nationality'])
query.kind.add().name = kind
datastore_helper.set_property_filter(query.filter, '__key__', PropertyFilter.EQUAL, parent_key)
req = helper.make_request(project=PROJECT, namespace=parent_key.partition_id.namespace_id,query=query)
resp = helper.get_datastore(PROJECT).run_query(req)
if len(resp.batch.entity_results) > 0:
existing_entity = resp.batch.entity_results[0].entity
existing_child_name_v = datastore_helper.get_value(existing_entity.properties['child_name'])
new_child_names = existing_child_name_v + ';' + datastore_helper.get_value(element.properties['child_name'])
datastore_helper.set_value(element.properties['child_name'],new_child_names)
return [element]
else:
return [element]
答案 0 :(得分:1)
UpdateEntities是束流中最慢的部分也就不足为奇了。您在对UpdateEntities的每个调用中都要进行RPC(您应该使用get / lookup而不是对键的查询,因为对键的查询最终是一致的)。只要您在UpdateEntities中执行RPC,它将是您工作中最慢的部分。