2012-09-02 33 views
0

因此,在讀取SQLAlchemy ordering by count on a many to many relationship之後,我嘗試複製結果,但它無法正常工作。所以,我的模型,SQLAlchemy通過映射表中的關係排序

class Group(Base): 
__tablename__='groups' 
__table_args__={ 
    'mysql_engine':'InnoDB', 
    'mysql_charset':'utf8', 
} 

id = Column(Integer, primary_key=True, unique=True) 
name = Column(VARCHAR(30), primary_key=True, unique=True) 
time = Column(DateTime, onupdate = datetime.datetime.now) 
description = Column(VARCHAR(255)) 
creator_id = Column(Integer, ForeignKey('users.id')) 
privacy = Column(SMALLINT) # 0 == public, 1 == friends, 2 == private 

def __init__(self, name, descr, creator, privacy): 
    self.name = name 
    self.description = descr 
    self.creator_id = creator 
    self.privacy = privacy 

class GroupUserRelationship(Base): 
__tablename__='groupUserRelationships' 
__table_args__={ 
    'mysql_engine':'InnoDB', 
    'mysql_charset':'utf8', 
} 

id = Column(Integer, primary_key = True) 
group_id = Column(Integer, ForeignKey('groups.id')) 
user_id = Column(Integer, ForeignKey('users.id')) 
time = Column(DateTime, onupdate=datetime.datetime.now) 

def __init__(self, group, user): 
    self.group_id = group 
    self.user_id = user 

和我SQLAlchemy的查詢是groups = session.query(Group, func.count(GroupUserRelationship.user_id).label('total')).join(GroupUserRelationship).group_by(Group).order_by('total DESC').limit(20).all(),但是當我嘗試遍歷它返回的列表,並進入該組的ID,我得到一個AttributeError:「NamedTuple」不具有屬性ID 。發生什麼事了?

回答

2

這種形式的查詢:

session.query(Group, func.count(GroupUserRelationship.user_id).label('somelabel')) 

將返回元組的列表如下:

[ 
    (group1, 5), 
    (group2, 7), 
    ... 
] 

..等

迭代來獲得在group.id然後:

for group, user_id in session.query(Group, func.count(GUR.user_id).label('somelabel')).join(...): 
    print group.id 

對於t他認爲,我認爲第一個重要的技術是養成整排不分組的習慣(即GROUP_BY(組))。雖然這裏的查詢可以使用該技術進行工作,但這種做法很糟糕,因爲您正在使數據庫執行大量與整個組表中的所有列相匹配的額外工作,而實際上您需要分組的所有列都是單列GroupUserRelationship.user_id 。關於這個文章,我參考這篇文章http://weblogs.sqlteam.com/jeffs/archive/2005/12/14/8546.aspx。 SQLAlchemy教程然後在此處以此表單爲例:http://docs.sqlalchemy.org/en/rel_0_7/orm/tutorial.html#using-subqueries

接下來的事情在SQLAlchemy中真正好用的是使用關係()在兩個類之間建立特定的連接路徑。所以在這裏,使用子查詢完成分組表達式。這裏使用的特殊技巧是可選的,你可以說join(subquery, Group.gur)這意味着「使用Group.gur關係的等價連接條件連接到這個子查詢」。

編輯說明一個完整的往返例如

from sqlalchemy import * 
from sqlalchemy.orm import * 
from sqlalchemy.ext.declarative import declarative_base 

Base = declarative_base() 

class Group(Base): 
    __tablename__ = 'groups' 

    id = Column(Integer, primary_key=True) 
    name = Column(VARCHAR(30)) 
    gur = relationship("GroupUserRelationship") 

class GroupUserRelationship(Base): 
    __tablename__ = 'groupUserRelationships' 

    id = Column(Integer, primary_key=True) 
    group_id = Column(Integer, ForeignKey('groups.id')) 

e = create_engine("sqlite://", echo=True) 
Base.metadata.create_all(e) 

s = Session(e) 

s.add_all([ 
    Group(name='g1', gur=[GroupUserRelationship() for i in xrange(3)]), 
    Group(name='g2', gur=[GroupUserRelationship() for i in xrange(8)]), 
    Group(name='g3', gur=[GroupUserRelationship() for i in xrange(5)]), 
    Group(name='g4', gur=[GroupUserRelationship() for i in xrange(1)]), 
    Group(name='g5', gur=[GroupUserRelationship() for i in xrange(2)]), 
]) 
s.commit() 


gur_count = s.query(
       func.count(GroupUserRelationship.id).label('total'), 
       GroupUserRelationship.group_id 
      ).group_by(GroupUserRelationship.group_id).\ 
      subquery() 

for group, gur_count in s.query(Group, gur_count.c.total).\ 
      join(gur_count, Group.gur).\ 
      order_by(gur_count.c.total): 
    print "GROUP:", group.name, "GROUP ID:", group.id, "NUMBER OF GUR:", gur_count 

輸出(減SQL呼應,看看發生了什麼事,這是有用):

GROUP: g4 GROUP ID: 4 NUMBER OF GUR: 1 
GROUP: g5 GROUP ID: 5 NUMBER OF GUR: 2 
GROUP: g1 GROUP ID: 1 NUMBER OF GUR: 3 
GROUP: g3 GROUP ID: 3 NUMBER OF GUR: 5 
GROUP: g2 GROUP ID: 2 NUMBER OF GUR: 8 
+0

有沒有辦法對它們進行排序? – Wiz

+0

通過關係計數 – Wiz

+0

oke doke,即添加 – zzzeek