英文:
Sqlalchemy count of records in the relation of one to many
问题
帮我找出我做错了什么?
我需要获取一对多表中24小时内的评论数量。
我不知道查询是否正确,甚至是否输出记录数量。
以下是请求本身:
我收到了这个错误:
英文:
Help me figure out what I'm doing wrong?
I need to get the number of comments in 24 hours in the relation one-to-many table.
class Comment(Base):
__tablename__ = 'comments'
id = Column(Integer, primary_key=True)
task_id = Column(Integer(), ForeignKey('tasks.id'), nullable=False)
post_link = Column(String, nullable=False)
date = Column(DateTime, default=datetime.datetime.utcnow())
def __init__(self, task_id: int, post_link: str):
super().__init__()
self.task_id = task_id
self.post_link = post_link
def __repr__(self):
return f'id - {self.id} | task_id - {self.task_id} | date - {self.date}'
class Task(Base):
__tablename__ = 'tasks'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
comments = relationship('Comment', backref='tasks', lazy=True)
def __init__(self, name: str):
super().__init__()
self.name = name
def __repr__(self):
return f'id - {self.id} | name - {self.name}'
I don't know if the query works correctly or if it even outputs the number of records.
Here's the request itself:
async def get_comments_for_day():
start_day = datetime.utcnow() - timedelta(hours=23, minutes=50)
async with get_async_session() as session:
stmt = select(Comment.task_id, func.count(Comment.task_id).label('comments_found'))\
.where(Comment.date >= start_day).subquery()
main_stmt = select(Task, stmt.c.comments_found).outerjoin(stmt, Task.id == stmt.c.task_id)
results = await session.execute(main_stmt)
return results.scalars().all()
async def main():
tasks = await get_comments_for_day()
for task, comments_found in tasks:
print(task.name, comments_found)
I get this error:
for task, comments_found in tasks:
TypeError: cannot unpack non-iterable Task object
答案1
得分: 1
你正在迭代tasks
,每个task
,但问题是每个任务都是一个Task
、count
的元组,不仅仅是一个Task
对象。
只需将打印语句更改为引用正确的索引
编辑:让我们尝试直接在查询中指定属性,例如id和name,并且我们将使用group_by()
来对任务进行分组,然后计算每个任务的评论数。
async def get_comments_for_day():
start_day = datetime.utcnow() - timedelta(hours=23, minutes=50)
async with get_async_session() as session:
stmt = (
select(Task.id, Task.name, func.count(Comment.id).label('comments_found'))
.select_from(Task)
.join(Comment, Task.id == Comment.task_id, isouter=True)
.where(Comment.date >= start_day)
.group_by(Task.id, Task.name)
)
result = await session.execute(stmt)
return result.scalars().all()
async def main():
tasks = await get_comments_for_day()
for task_id, task_name, comments_found in tasks:
print(task_name, comments_found)
请注意,这是你提供的代码的翻译版本,没有其他内容。
英文:
You are iterating over tasks
, each task
, but the thing is each task is a tuple of Task
, count
, not just a Task
object.
Just change the print statement to reference the correct index
edit: lets try to directly specify the attributes in the query, such as id and name and also we will group_by()
to group the results by task and then count the comments for each
async def get_comments_for_day():
start_day = datetime.utcnow() - timedelta(hours=23, minutes=50)
async with get_async_session() as session:
stmt = (
select(Task.id, Task.name, func.count(Comment.id).label('comments_found'))
.select_from(Task)
.join(Comment, Task.id == Comment.task_id, isouter=True)
.where(Comment.date >= start_day)
.group_by(Task.id, Task.name)
)
result = await session.execute(stmt)
return result.scalars().all()
async def main():
tasks = await get_comments_for_day()
for task_id, task_name, comments_found in tasks:
print(task_name, comments_found)
答案2
得分: 0
async def get_comments_for_day():
start_day = datetime.utcnow() - timedelta(hours=24)
async with get_async_session() as session:
stmt = (
select(func.count(Comment.id), Task)
.select_from(Task)
.join(Comment, Task.id == Comment.task_id, isouter=True)
.where(Comment.date >= start_day)
.group_by(Task.id, Task.name)
)
results = await session.execute(stmt)
return results.all()
If you're interested, I found a solution to the problem, which was to write return results.all()
instead of return results.execute().all()
.
英文:
async def get_comments_for_day():
start_day = datetime.utcnow() - timedelta(hours=24)
async with get_async_session() as session:
stmt = (
select(func.count(Comment.id), Task)
.select_from(Task)
.join(Comment, Task.id == Comment.task_id, isouter=True)
.where(Comment.date >= start_day)
.group_by(Task.id, Task.name)
)
results = await session.execute(stmt)
return results.all()
If you're interested, I found a solution to the problem, which was to write return results.all()
instead of return results.execute().all()
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论