2013-05-17 63 views
0

我開發簡單的博客與標記支持。其實我想添加標籤雲功能,我需要計算每個標籤在博客中使用。 我的博客和標籤模型的樣子:瓶頸如何計算標籤計數

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提供了連接功能? 問:如何使用Python燒瓶SQLAlchemy的查詢關鍵詞,比如執行以下操作:

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 

回答

2

試試這個:

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.countdb.count。無論如何,你總是可以使用from sqlalchemy import func並使用func.count

+0

'query.join(Post.tags)'應該可以工作。我還建議不要採用第一種方式(隱式加入),顯式聯接的確看起來更清晰。 –

+0

@AudriusKažukauskas這就是我的想法,'query.join(Post)'應該可以工作IIRC,但它只是引發了一個異常,說它找不到外鍵將'posts'鏈接到'tags'。我的猜測是關係有問題,或者只有'query.join(Post.tags)'有效。我會試試看,究竟是什麼錯... – jadkik94

+0

我認爲'query.join(Post)'不起作用,因爲這是一個涉及到關聯表的多對多關係。 –

1

我會做這樣(僞代碼,不記得正確的煉丹語法,但你應該能夠「轉換」它安靜容易)

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

,並在和你應該在myDict所有標籤與他們的計數

+0

謝謝,我已經檢查過它。這是相當明顯的,但不是太有效 - 每個標籤我有1個額外的查詢。 –