построение запроса sqlalchemy
Суть такая. Есть 2 таблицы Client и MessageToWeb:
class Client(Base):
__tablename__ = "client"
client_id = Column(BigInteger, primary_key=True, autoincrement=False)
username = Column(String(60), nullable=True)
client_url = Column(String(130), nullable=False)
name = Column(String(130), nullable=False)
city = Column(String(70), nullable=False)
tattoo_type = Column(String(60), nullable=False)
date_of_reg = Column(DateTime, nullable=False, server_default=func.now())
is_advertising_allowed = Column(Boolean, default=True, nullable=False)
is_model = Column(Boolean, default=False, nullable=False)
is_bot_usage_consent = Column(Boolean, default=False, nullable=False)
is_blocked = Column(Boolean, default=False, nullable=False)
complaints = relationship(
"Complaints", back_populates="client", cascade="delete, delete-orphan"
)
likes = relationship(
"Likes", back_populates="client", cascade="delete, delete-orphan"
)
contact_requests = relationship(
"ContactRequests", back_populates="client", cascade="delete, delete-orphan"
)
styles = relationship(
"ClientStyles", back_populates="client", cascade="delete, delete-orphan"
)
messages = relationship(
"MessageToWeb", backref="client", cascade="delete, delete-orphan",
)
class MessageToWeb(Base):
__tablename__ = "message_to_web"
message_id = Column(BigInteger, primary_key=True, autoincrement=True)
user_id = Column(BigInteger, ForeignKey("client.client_id"), autoincrement=False, nullable=False)
master_id = Column(BigInteger, ForeignKey("master.master_id"), autoincrement=False, nullable=False)
text = Column(String(1200), nullable=False)
destination = Column(String(400), nullable=False)
complaint_date = Column(DateTime, nullable=False, server_default=func.now())
Нужно одним запросом к БД получить вот такую структуру:
{
6373403021: {
"client_id": 6373403021,
"name": "TEST",
"tattoo_type": "Оба варианта",
"is_advertising_allowed": true,
"is_bot_usage_consent": true,
"username": "sprint_me_plz",
"client_url": "https://123123z.ru",
"city": "Екатеринбург",
"date_of_reg": "2024-01-12T15:50:43.662963",
"is_model": true,
"is_blocked": false,
"messages": [
{
"message_id": 11,
"text": "Аууууу",
"complaint_date": "2024-01-13T18:19:39.881672",
"destination": "master",
"user_id": 343526452,
"master_id": 11111111000000001
}
]
},
6373403021: {
"client_id": 6373403021,
"name": "TEST",
"tattoo_type": "Оба варианта",
"is_advertising_allowed": true,
"is_bot_usage_consent": true,
"username": "adasff",
"client_url": "https://ttee.test",
"city": "Екатеринбург",
"date_of_reg": "2024-01-12T15:50:43.662963",
"is_model": true,
"is_blocked": false,
"messages": [
{
"message_id": 11,
"text": "Аууууу",
"complaint_date": "2024-01-13T18:19:39.881672",
"destination": "master",
"user_id": 3242536,
"master_id": 11111111000000001
}
],
}
}
Т.е. надо получить всех пользователей вместе со всеми их сообщениями. Читал про разные вариации JOIN, но не понял как их применить. Возможно это простая задача, но никак не могу сообразить. Пытался вот так, но четно:
result = await session.execute(select(Client)
.join(MessageToWeb)
.where(Client.client_id==MessageToWeb.user_id)
.order_by(Client.client_id.desc())
.distinct()
)
user_list = result.scalars().all()
return jsonable_encoder(user_list)
Построил запрос в postgresql:
FROM client c
JOIN (
SELECT user_id, MAX(complaint_date) AS latest_timestamp
FROM message_to_web
GROUP BY user_id
) m ON c.client_id = m.user_id
JOIN message_to_web m2 ON m.user_id = m2.user_id AND m.latest_timestamp = m2.complaint_date;
но не понимаю, как перевести его в ORM