You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Flask SQLAlchemy查询多对多中间表的点赞统计(无冗余关联)

SQLAlchemy实现指定商品点赞数统计(避免不必要关联)

首先明确你的模型结构(基于Flask-SQLAlchemy):

from flask_sqlalchemy import SQLAlchemy
import uuid

db = SQLAlchemy()

# 多对多中间表定义
customers_favorite_items = db.Table(
    'customers_favorite_items',
    db.Column('customer_id', db.UUID, db.ForeignKey('customers.id'), primary_key=True),
    db.Column('item_id', db.UUID, db.ForeignKey('items.id'), primary_key=True)
)

class Customer(db.Model):
    __tablename__ = 'customers'
    id = db.Column(db.UUID, primary_key=True, default=uuid.uuid4)
    # 其他业务字段...
    favorite_items = db.relationship(
        'Item',
        secondary=customers_favorite_items,
        back_populates='favorited_by'
    )

class Item(db.Model):
    __tablename__ = 'items'
    id = db.Column(db.UUID, primary_key=True, default=uuid.uuid4)
    # 其他业务字段...
    favorited_by = db.relationship(
        'Customer',
        secondary=customers_favorite_items,
        back_populates='favorite_items'
    )

核心实现思路

要避免不必要的关联,核心是直接操作中间统计数据,不加载Customer表的任何数据——因为你只需要点赞数,不需要客户的具体信息。以下是两种常用实现方式:

方式一:仅统计点赞数(直接查询中间表)

对应你提到的原生SQL逻辑,直接查询customers_favorite_items中间表,无需关联任何业务表:

from sqlalchemy import func

def get_item_like_counts(item_uuids):
    # 直接从中间表聚合统计
    count_results = db.session.query(
        customers_favorite_items.c.item_id,
        func.count(customers_favorite_items.c.customer_id).label('like_count')
    ).filter(
        customers_favorite_items.c.item_id.in_(item_uuids)
    ).group_by(
        customers_favorite_items.c.item_id
    ).all()

    # 转换为易读的字典结构
    return {str(item_id): like_count for item_id, like_count in count_results}

方式二:统计+商品基础信息(仅关联Item表)

如果需要同时返回商品的其他字段(如名称、描述),只需关联Item表,依然不碰Customer表:

from sqlalchemy import func

def get_items_with_like_counts(item_uuids):
    # 先子查询统计点赞数
    like_count_subquery = db.session.query(
        customers_favorite_items.c.item_id,
        func.count(customers_favorite_items.c.customer_id).label('like_count')
    ).filter(
        customers_favorite_items.c.item_id.in_(item_uuids)
    ).group_by(
        customers_favorite_items.c.item_id
    ).subquery()

    # 关联Item表获取商品信息,用outerjoin保证无点赞的商品也能返回(点赞数为0)
    items_data = db.session.query(
        Item,
        like_count_subquery.c.like_count
    ).outerjoin(
        like_count_subquery,
        Item.id == like_count_subquery.c.item_id
    ).filter(
        Item.id.in_(item_uuids)
    ).all()

    return [
        {
            'item_id': str(item.id),
            'item_name': item.name,  # 替换为你的实际字段
            'like_count': like_count or 0
        } for item, like_count in items_data
    ]

为什么能避免不必要关联?

  • 方式一完全绕过业务表,直接从中间统计表获取数据,没有任何join操作;
  • 方式二仅关联Item表获取必要信息,全程不涉及Customer表的关联或数据加载,避免了多余的查询开销。

内容的提问来源于stack exchange,提问作者ზურა კუპატაძე

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 17:12:50