2011-06-25 20 views
16

SQLAlchemy 0.7.1 और एक MySQL 5.1 डेटाबेस का उपयोग करना, मुझे मिल गया है एक कई-से-अनेक संबंध के रूप में स्थापित इस प्रकार है:SQLAlchemy: में सदस्यता द्वारा फिल्टर कम से कम एक कई करने के लिए कई संबंधित तालिका

user_groups = Table('user_groups', Base.metadata, 
    Column('user_id', String(128), ForeignKey('users.username')), 
    Column('group_id', Integer, ForeignKey('groups.id')) 
) 

class ZKUser(Base, ZKTableAudit): 
    __tablename__ = 'users' 

    username = Column(String(128), primary_key=True) 
    first_name = Column(String(512)) 
    last_name = Column(String(512)) 

    groups = relationship(ZKGroup, secondary=user_groups, backref='users') 

class ZKGroup(Base, ZKTableAudit): 
    __tablename__ = 'groups' 

    id   = Column(Integer, primary_key=True) 
    name  = Column(String(512)) 

उपयोगकर्ता कई समूह से संबंधित हो सकते हैं, और समूह में एकाधिक उपयोगकर्ता हो सकते हैं।

जो मैं करने की कोशिश कर रहा हूं वह एक स्क्लेक्लेमी क्वेरी बनाता है जो केवल उन उपयोगकर्ताओं को लौटाता है जो समूह की सूची में से कम से कम एक समूह से संबंधित हैं।

मैंने in_ फ़ंक्शन के साथ खेला, लेकिन यह केवल सूची में सदस्यता के लिए स्केलर मानों का परीक्षण करने के लिए काम करता है। मैं एक एसक्यूएल लेखक का अधिक नहीं हूं, इसलिए मुझे यह भी पता नहीं है कि SELECT कथन किस प्रकार की आवश्यकता होगी।

उत्तर

29

ठीक है, अनुसंधान के एक बहुत बाद, मुझे एहसास हुआ कि यह एसक्यूएल शब्दावली है कि मुझे पकड़े हुए था वापस की अपने ही अज्ञान था। समूहों की सूची में से "कम से कम" से संबंधित उपयोगकर्ताओं को ढूंढने के समाधान के लिए मेरी खोज को समूहों की सूची के "किसी भी" से संबंधित उपयोगकर्ताओं को ढूंढना चाहिए था।

session.query(ZKUser).filter(ZKUser.groups.any(ZKGroup.id.in_([1,2,3]))) 

कि कोड इस एसक्यूएल (MySQL 5.1 पर) का उत्सर्जन करता है:

SELECT * FROM users 
WHERE EXISTS (
    SELECT 1 FROM user_groups, groups 
    WHERE users.id = user_groups.contact_id 
     AND groups.id = user_groups.group_id 
     AND groups.id IN (%s, %s, %s) 
    ) 
+0

सदस्यता से फ़िल्टर करके कई से अधिक संबंधित टेबल पर फ़िल्टर कैसे किया जाता है? – WebPal

+1

आपका उत्तर संदर्भ 'ZKContact' और' संपर्क 'है, लेकिन ये प्रश्न में आपके कोड में नहीं हैं। क्या आपका मतलब ZKUser था? –

+0

वोटिंग उत्तर नीचे, यह प्रश्न के मुकाबले अलग-अलग कीवर्ड का उपयोग कर रहा है, और संभव समाधान का पालन करना मुश्किल है। – Drachenfels

0

आप in_ उपयोग कर सकते हैं:

session.query(ZKUser).filter(ZKGroup.id.in_([1,2])).all() 
+0

मैं इस एक शॉट दे देंगे सप्ताहांत। यह आशाजनक लग रहा है। इसके अलावा, मुझे अपने वर्ग के नाम और आपका उपयोगकर्ता नाम का संयोग पसंद है। :) मेरा "जेडके" मेरे ऐप का नाम जुकीपर के लिए खड़ा है। यह MailChimp के एपीआई के साथ इंटरफेस करता है। – CoreDumpError

+0

दुर्भाग्य से, यह काम नहीं किया। मुझे लगता है कि ऐसा इसलिए है क्योंकि यह वास्तविक जुड़ाव नहीं कर रहा है, इसलिए इस द्वारा उत्सर्जित एसक्यूएल वास्तव में गैर-मिलान करने वाले उपयोगकर्ताओं को फ़िल्टर नहीं करता है। मैंने कई-से-कई तालिकाओं में शामिल होने के लिए स्क्लेक्लेमी पर दस्तावेज़ों की जांच की है, लेकिन मैं पूरी तरह से खो गया हूं। – CoreDumpError

+1

आप 'session.query (ZKUser) .join (ZKGroup) .filter (..) 'करने का प्रयास कर सकते हैं। यह 0.7.2, afaik में काम करना चाहिए। – zeekay

3

the docs for any के अनुसार, क्वेरी तेजी से करता है, तो चलेंगे SQLAlchemy से any ORM समारोह मैं, वास्तव में क्या जरूरत है तो तरह करता है आप एक स्पष्ट join बजाय का उपयोग करें:

क्योंकि किसी भी() एक सहसंबद्ध सबक्वेरी का उपयोग करता है, इसके प्रदर्शन को लगभग रूप में अच्छा है जब के रूप में बड़े लक्ष्य तालिकाओं के खिलाफ तुलना नहीं की है शामिल होने का उपयोग करना।

आपके मामले में, आप कुछ कर सकते हैं की तरह:

users = (
    session.query(ZKUser) 
    .join(user_groups) 
    .filter(user_groups.columns.group_id.in_([1, 2, 3])) 
) 

यह उत्सर्जन करता है एसक्यूएल की तरह: जब मैं के बाद कार्यालय के लिए वापस पाने के

SELECT * 
FROM users 
JOIN user_groups ON users.id = user_groups.user_id 
WHERE user_groups.group_id IN (1, 2, 3) 
संबंधित मुद्दे