我每隔几个小时就会收到一个复杂的json,其中一部分是一个Game
对象,包含一个Player
对象列表,每个Player
都包含一个Training
对象列表。(每个对象还有其他字段-int,字符串,字符串列表等)。如果Game
对象在我的Postgres数据库中不存在,(我通过Game
的id字段进行检查),我将整个结构插入到数据库中,每个对象作为其自己的表(Game
的一个表,Player
的一个表和Training
的一个表)。下次我获取这个Game
的json时,它已经存在于数据库中,所以我想更新它。我得到了旧的json,更新的json和json_patch。我想查询db,将其转换为json,并在json上应用补丁。问题是,(例如球员)与updated_object
json中的列表排序方式不同。但我需要在db上工作,因为我需要有对象的主键,以便ORM知道哪些对象最新情况。最好的方法是什么?
型号:
class Game(Base):
__tablename__ = "game"
game_id: int = Column(INTEGER, primary_key=True,
server_default=Identity(always=True, start=1, increment=1, minvalue=1,
maxvalue=2147483647, cycle=False, cache=1),
autoincrement=True)
unique_id: str = Column(TEXT, nullable=False)
name: str = Column(TEXT, nullable=False)
players = relationship('Player', back_populates='game')
class Player(Base):
__tablename__ = "player"
player_id: int = Column(INTEGER, primary_key=True,
server_default=Identity(always=True, start=1, increment=1, minvalue=1,
maxvalue=2147483647, cycle=False, cache=1),
autoincrement=True)
unique_id: str = Column(TEXT, nullable=False)
game_id: int = Column(INTEGER, ForeignKey('game.game_id'), nullable=False)
name: str = Column(TEXT, nullable=False)
birth_date = Column(DateTime, nullable=False)
game = relationship('Game', back_populates='players')
trainings = relationship('Training', back_populates='player')
class Training(Base):
__tablename__ = "training"
training_id: int = Column(INTEGER, primary_key=True,
server_default=Identity(always=True, start=1, increment=1, minvalue=1,
maxvalue=2147483647, cycle=False, cache=1),
autoincrement=True)
unique_id: str = Column(TEXT, nullable=False)
name: str = Column(TEXT, nullable=False)
number_of_players: int = Column(INTEGER, nullable=False)
player_id: int = Column(INTEGER, ForeignKey('player.player_id'), nullable=False)
player = relationship('Player', back_populates='players')
字符串
JSON更新数据:
{"original_object":{"name":"Table Tennis","unique_id":"432","players":[{"unique_id":"793","name":"John","birth_date":"2023-10-28T00:10:56Z","trainings":[{"unique_id":"43","name":"Morning Session","number_of_players":3}, {"unique_id":"44","name":"Evening Session","number_of_players":2}]}]},"updated_object":{"name":"Table Tennis","unique_id":"432","players":[{"unique_id":"793","name":"John","birth_date":"2023-10-28T00:10:56Z","trainings":[{"unique_id":"43","name":"Morning Session","number_of_players":3}, {"unique_id":"44","name":"Evening Session","number_of_players":4}]}]},"json_patch":[{"op":"replace","path":"/players/0/trainings/1/numbre_of_players","value":4}],"timestamp":"2023-10-28T02:00:36Z"}
型
json_patch将第二次训练的'numbre_of_players'字段更新为值4。
添加新游戏的代码:
Session = sessionmaker(bind=engine_sync)
session = Session()
session.begin()
game = Game.from_dict(json['updated_object'])
existing_game = session.query(Game).filter_by(unique_id=game.id).first()
if not existing_game:
session.add(game)
session.commit()
型
但是如果Game
已经存在于数据库中,我不确定我应该做什么。
1条答案
按热度按时间gcxthw6b1#
这看起来像是
sqlalchemy.orm.Session.merge()
的任务。您正在查看同一个Game
的3种可能状态:1.一个在数据库中,
1.一个在你的治疗中,
1.另一个,无论你从哪里得到这个更新的状态,
你想更新/覆盖前两个状态,假设第三个是真的。
字符串
不需要检查它是否已经在你的会话和/或数据库中,因为
merge()
会自动检查,如果它没有找到匹配的Game
,它会将其添加为一个新的。Session.merge()
检查源示例的主键属性,并尝试将其与会话中具有相同主键的示例进行协调。如果在本地找不到,则尝试根据主键从数据库加载对象,如果找不到,创建一个新示例。然后将源示例上的每个属性的状态复制到目标示例。然后返回结果目标示例通过该方法,原始源示例保持不变,并且如果尚未与Session
相关联,则与Session
解除关联。请记住相应地设置级联,以处理可能与之相关的所有对象。