2015-04-12 81 views
1

在我的瓶的應用程序,有許多到許多文件和標記之間的關係:的SQLAlchemy:在許多一對多的關係查詢過濾計數

DocTokens = db.Table(
    'DocTokens', 
    db.Column('token_id', db.Integer, db.ForeignKey('Token.id')), 
    db.Column('document_id', db.Integer, db.ForeignKey('Document.id')), 
    ) 

class Token(db.Model): 
    __tablename__ = 'Token' 
    id = db.Column(db.Integer, primary_key=True) 
    ... 
    is_gold = db.Column(db.Boolean, default=None) 

class Document(db.Model): 
    __tablename__ = 'Document' 
    id = db.Column(db.Integer, primary_key=True) 
    ... 
    tokens = db.relationship(
     'Token', 
     secondary=DocTokens, 
     backred=db.backref('documents', lazy='dynamic'), 
     ) 

我想構建一個文檔查詢,按相關令牌的數量排序(遞減),其中Token.is_gold爲無

到目前爲止,我已經想通了如何通過相關的令牌數量合同文檔:

db.session.query(
    Document, 
    func.count(DocTokens.c.token_id).label('total') 
    ).join(DocTokens).group_by(Document).order_by('total DESC') 

但是,我似乎無法使該計數僅包括令牌,其中Token.is_gold是無。這是多次失敗的嘗試之一:

db.session.query(
    Document, 
    func.count(DocTokens.c.token_id) 
    .filter(Token.is_gold.is_(None)).label('total') 
    ).join(DocTokens).group_by(Document).order_by('total DESC') 

它扔了以下錯誤:

AttributeError: Neither 'count' object nor 'Comparator' object has an attribute 'filter' 

下面是一些StackOverflow的解決方案,我一直在努力,模型包含子和混合性(包括解決方案。 ):

我是相當新的SQL/SQLAlchemy的...任何幫助是非常感謝!

+0

你能表達你的查詢在純sql嗎? –

+0

感謝您在回覆您的評論之前回答此問題。我嘗試了幾個小時來制定SQL,但我無法得到它的工作......非常感謝! – NTS

回答

3
  • label應適用於func.count(DocTokens.c.token_id),而不是過濾器對象。你在第一個查詢中是正確的,但不是在第二個查詢中。

  • filterquery對象的一個​​方法,所以必須將其寫爲:

    db.session.query(...).join(...).filter(...).group_by(...).order_by(...) 
    
  • 過濾器被施加於從Token一列,所以這必須包括在所述加入。

因此,寫爲下面的查詢不會給你一個錯誤:

r = db.session.query(Document, 
        func.count(Token.id).label('total'))\ 
    .join(DocTokens).join(Token)\ 
    .filter(Token.is_gold.is_(None))\ 
    .group_by(Document)\ 
    .order_by('total DESC') 

這將產生以下SQL(使用SQLite作爲後端)

'SELECT "Document".id AS "Document_id", count("DocTokens".token_id) AS total \nFROM "Token", "Document" JOIN "DocTokens" ON "Document".id = "DocTokens".document_id \nWHERE "Token".is_gold IS NULL GROUP BY "Document".id ORDER BY total DESC'

更新:如果您不確定查詢對象會生成什麼樣的sql,您可以隨時使用str進行檢查,即

如果我在示例查詢中運行str(r),它將打印上面引用的sql。

+0

這很好用=)並且,謝謝你的解釋! – NTS

+0

很高興幫助。用小提示更新答案。 –

相關問題