【问题标题】:Flask how to calculate tags countFlask如何计算标签数
【发布时间】:2013-05-12 10:14:57
【问题描述】:

我正在开发带有标签支持的简单博客。实际上我想添加标签云功能,我需要计算博客中使用的每个标签。 我的博客和标签模型如下所示:

class Blog(db.Model, ObservableModel):
    __tablename__ = "blogs"

    id = db.Column(db.Integer, db.Sequence('blog_id_seq'), primary_key=True)
    title = db.Column(db.String(200), unique=True, nullable=True)

    tags = relationship('Tag', secondary=tags_to_blogs_association_table)

class Post(db.Model, ObservableModel):
    __tablename__ = "posts"

    ......................

    blog = relationship('Blog', backref = db.backref('blogs', lazy='dynamic'))
    tags = relationship('Tag', secondary=tags_to_posts_association_table)

class Tag(db.Model):
    __tablename__ = "tags"

    id = db.Column(db.Integer, db.Sequence('post_id_seq'), primary_key=True)
    title = db.Column(db.String(30), unique=False, nullable=True)

我想收集像 tag_name : count 这样的字典对,只有一种方法是遍历 Blog.tags 集合并检索包含标签项的帖子。 实际上我不确定它是否是最好的(从性能的角度来看)解决方案,也许flask-sqlalchemy 提供了连接功能? 问题:如何使用 Flask-SQLAlchemy 查询在 Python 中实现,如下所示:

select
    t.id,
    t.title,
    count(post_id)
from tags t
join tags_to_blogs b on t.id=b.tag_id
join tags_to_posts p on t.id=p.tag_id
group by (t.id)
having b.blog_id=1

【问题讨论】:

    标签: python sqlite sqlalchemy flask


    【解决方案1】:

    试试这个:

    query = db.session.query(Tag, db.count(Post.id))
    query = query.filter(
        (tags_to_posts_association_table.tag_id == Tag.id) & \
        (tags_to_posts_association_table.post_id == Post.id)
    )
    query = query.group_by(Tag.id)
    

    这会生成这个查询:

    SELECT tags.id AS tags_id, tags.title AS tags_title, count(posts.id) AS count_1 
    FROM tags, posts, tags_to_posts 
    WHERE tags_to_posts.tag_id = tags.id AND tags_to_posts.post_id = posts.id GROUP BY tags.id
    

    更简洁的方法可能是这样的:

    query = db.session.query(Tag, db.func.count(Post.id))
    # This works but the preferred way is what's below it
    #query = query.join(tags_to_posts_association_table, Post)
    query = query.join(Post.tags)
    query = query.group_by(Tag.id)
    

    这会生成这个查询:

    SELECT tags.id AS tags_id, tags.title AS tags_title, count(posts.id) AS count_1 
    FROM tags INNER JOIN tags_to_posts ON tags.id = tags_to_posts.tag_id INNER JOIN posts ON posts.id = tags_to_posts.post_id GROUP BY tags.id
    

    所有这些都会产生相同的结果,您可以像这样链接它们:

    query = db.session.query(Tag.title, db.func.count(Post.id)).join(Post.tags).group_by(Tag.id)
    
    # This will give you a dictionary with keys the tag titles, and values the count of each
    # Because you can iterate over the query, which will give you the results
    # Or you can use query.all() and use it as you prefer.
    results = dict(query)
    

    另外,我不确定是db.func.count 还是db.count。无论如何,您始终可以from sqlalchemy import func 和使用func.count

    【讨论】:

    • query.join(Post.tags) 应该可以工作。我还建议不要使用第一种方式(隐式连接),显式连接确实看起来更干净。
    • @AudriusKažukauskas 我也是这么想的,query.join(Post) 应该可以工作 IIRC,但它只是提出了一个异常,说它找不到将 posts 链接到 tags 的外键。我的猜测是关系有问题,或者可能只有query.join(Post.tags) 有效。我会试试看到底是哪里出了问题...
    • 我认为query.join(Post) 不起作用,因为这是涉及关联表的多对多关系。
    【解决方案2】:

    我会这样做(伪代码,不记得正确的炼金术语法,但你应该能够轻松地“转换”它安静)

    tags = Tags.findAll()
    for tag in tags:
        myDict[tag] = Post.find(tags=tag).count()
    

    然后你应该在 myDict 中拥有所有标签及其计数

    【讨论】:

    • 谢谢,我已经查过了。这很明显,但不是太有效 - 对于每个标签,我都有 1 个额外的查询。
    猜你喜欢
    • 1970-01-01
    • 2011-07-12
    • 2017-05-30
    • 2013-10-19
    • 2018-03-25
    • 2022-07-06
    • 2020-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多