如何在Google Datastore中实现仅键不存在时写入实体
Datastore仅新增不覆盖写入的实现方案
核心实现逻辑
你需要放弃使用全量覆盖的Put()方法,改用「仅当键不存在时才写入」的逻辑,两种可落地的方案如下:
方案1:使用原生Insert接口(优先选用)
绝大多数Datastore官方SDK都提供了原生Insert()方法,和Put()的行为差异为:
Put():键存在则覆盖全量实体、键不存在则新增,会刷新已存在实体的timestamp字段Insert():仅键不存在时写入数据,键已存在时会抛出EntityAlreadyExists类异常,不会修改任何已有实体数据
你可以批量处理每日生成的实体,捕获已存在的异常直接跳过即可,参考Python SDK代码示例:
from google.cloud import datastore from google.api_core.exceptions import AlreadyExists client = datastore.Client() # 每日生成的实体数据 daily_entities = [ {"key": "a", "foo": "bar", "timestamp": "EXAMPLE_TIMESTAMP"}, {"key": "b", "foo": "baz", "timestamp": "EXAMPLE_TIMESTAMP"} ] for item in daily_entities: # 构造Datastore唯一键 key = client.key("你的实体Kind名称", item["key"]) entity = datastore.Entity(key=key) entity.update(item) try: client.insert(entity) except AlreadyExists: # 已存在实体直接跳过,不会修改原有数据 continue
该方案是原子操作,性能最优,没有并发冲突风险。
方案2:事务包裹查询+写入(兼容无原生Insert的场景)
如果当前使用的SDK没有提供Insert接口,用事务包裹「先查后写」逻辑即可,必须加事务避免并发场景下的竞态问题:
from google.cloud import datastore client = datastore.Client() daily_entities = [...] # 你的每日实体数据 def insert_if_not_exists(item): # 开启事务保证操作原子性 with client.transaction(): key = client.key("你的实体Kind名称", item["key"]) # 先查询键是否存在 exist_entity = client.get(key) if not exist_entity: # 不存在才执行写入 entity = datastore.Entity(key=key) entity.update(item) client.put(entity) for item in daily_entities: insert_if_not_exists(item)
该方案兼容性更强,但因为多了一次查询操作,性能弱于方案1。
后续新增实体筛选
两种方案都不会修改已入库实体的任何字段,timestamp会永久保留首次入库的时间,你直接按当日timestamp过滤查询即可快速筛选出当日新增的实体,完全满足你的需求。
内容的提问来源于stack exchange,提问作者David Bryant
相关产品推荐
相关产品推荐

