2011-12-05 70 views
1

我想加載重複對象的集合。我的模型是這樣的:急切加載非單例集合

Item -> Identifier 

我想載入共享相同標識符項目(急切地)的集合,而忽略絕大多數包含一個項目或更少的集合。 ORM關係在兩個方向(Identifier.items和Item.identifier)中設置。該SQL看起來應該是這樣的:

SELECT * FROM Item WHERE identifier_id IN (
    SELECT identifier_id FROM Item GROUP BY identifier_id HAVING COUNT(*) > 1) 

回答

2

使用一個子查詢,這樣就可以實現如下:

q = (select([Item.identifier_id, func.count(Item.id).label("cnt")]). 
    group_by(Item.identifier_id).having(func.count(Item.id)>1)).alias("subq") 
qry = (session.query(Item).join(q, Item.identifier_id==q.c.identifier_id)) 
print qry # prints SQL statement generated 
items = qry.all() # result 
+0

是抗T查詢他'__table__'在這種方法中是必要的,更高性能?爲什麼不只是將'Item'加入到'Item'的另一個查詢中? – wberry

+0

它會導致一個查詢(而不是原來的解決方案中的3個),並只加載** **不需要'Identifier'對象的'Item'對象需要'Item'對象。我肯定會說它更有效率。 – van

+0

..查詢不需要使用'Table'對象:雖然:更新答案直接使用Objects ... – van

0

這裏是我最後使用的版本:

from sqlalchemy.sql.functions import count 
from sqlalchemy.orm import subqueryload 
# … 

repeats = (
    select(
     (Item.identifier, 
     count(Item.identifier))) 
    .group_by(Item.identifier) 
    .having(count(Item.identifier) > 1) 
    .alias()) 
for identifier in (
    sess.query(Identifier) 
     .join(repeats, repeats.c.identifier==Identifier.value) 
     .options(subqueryload(Identifier.items)) 
): 
    for item in identifier.items: 
     pass 

(標識符現在映射針對一個選擇,而不是由一個數據庫表,這使得支持導入快一點太)