2012-06-20 24 views
6

मैं इस तरह एक वर्ग:ग्रोवी/Grails कैसे वस्तुओं की सूची की बजाय वस्तुओं की एक सूची वापस करने के लिए?

class Foo { 
    static hasMany = [bars: Bar] 
} 

जब मैं लिखना:

Foo.getAll() 

मैं इस तरह Foo वस्तुओं की एक सूची प्राप्त करें:

[ Foo1, Foo2, Foo3 ] 

जब मैं लिखना:

Foo.getAll().bars 

मैं इस तरह Bar वस्तु की सूची की एक सूची प्राप्त:

[ [ Bar1, Bar2 ], [ Bar2, Bar3 ], [ Bar1, Bar4 ] ] 

लेकिन क्या मैं चाहता हूँ इस तरह Bar वस्तुओं की एक अद्वितीय सूची है:

[ Bar1, Bar2, Bar3, Bar4 ] 

मेरे अंतिम लक्ष्य एक अनूठा है उपरोक्त सूची में Bar वस्तु की id की सूची, इस तरह:

[ 1, 2, 3, 4 ] 

मैं ०१२३७०३७७२६१ के रूपांतरों की कोशिश की हैविधि और मैंने spread operator भी कोशिश की है लेकिन मुझे कोई भाग्य नहीं है।

उत्तर

8

जेनेरिक ग्रोवी क्लासेस (यानी गैर-गोर्म क्लासेस) के लिए, डेविड सही है कि flatten और unique का उपयोग करने का सबसे अच्छा तरीका है।

हालांकि आपके उदाहरण में, ऐसा लगता है कि आप कई सारे रिश्ते में GORM डोमेन ऑब्जेक्ट्स का उपयोग कर रहे हैं (अन्यथा आपको विशिष्टता की बाधा की आवश्यकता नहीं होगी)।

किसी डोमेन क्लास के लिए, आप एक ही चरण में ऐसा करने के लिए एचक्यूएल या मानदंड का उपयोग करने से सबसे अच्छे हैं। एक अतिरिक्त लाभ यह है कि इसके लिए जेनरेट किया गया एसक्यूएल अधिक कुशल है।

Foo.withCriteria { 
    bars { 
     projections { 
      distinct("id") 
     } 
    } 
} 

: इस के लिए

Bar.executeQuery("select distinct b.id from Foo f join f.bars b") 

मापदंड दिखाई देगा:

यहाँ अद्वितीय Bar आईडी है कि एक बहुत-से-अनेक संबंध में किसी भी Foo से जुड़े हुए हैं प्राप्त करने के लिए HQL है इस तरह की विधि का उपयोग करने के साथ एक "मुद्दा" यह है कि एचक्यूएल यूनिट परीक्षणों में समर्थित नहीं है (और संभवतः कभी नहीं होगा) और Criteria queries with join table projections are broken in 2.0.4 unit tests। तो इस कोड के आस-पास के किसी भी परीक्षण को या तो मजाक करने या एकीकरण परीक्षण का उपयोग करने की आवश्यकता होगी।

+1

+1 यह इस मामले में जाने का सबसे अच्छा तरीका है :) – epidemian

+0

हाँ, सहमत :) – David

+0

आपके सभी उत्तरों के लिए धन्यवाद। इच्छा है कि मैं आपको और अधिक बढ़ा सकता हूं :) मैं एचक्यूएल से बचना चाहता था, लेकिन मानदंडों का उपयोग करके लगभग अपनी खोज पूरी कर ली, अब मुझे पेजिनेशन मिल रहा है ... परेशानी है। अगर मुझे मानदंडों का उपयोग करके अच्छा खेलने के लिए अंकन नहीं मिल रहा है तो मुझे लगता है कि मुझे लगता है कि एचक्यूएल पर जाना होगा। – ubiquibacon

4

एक बेहतर तरीका हो सकता है, लेकिन आप flatten और unique का उपयोग कर सकते हैं।

कुछ की तरह:

def allBars = Foo.getAll().bars.flatten().unique()

संपादित करें:
मैं सिर्फ फिर से पढ़ सकते हैं और देखते हैं कि आप अंत में आईडी की सूची के बाद बार्स कर रहे हैं, नहीं गए हैं। जैसा कि आपने सुझाव दिया है कि आप आईडी प्राप्त करने के लिए collect{ it.id } का उपयोग करेंगे। प्रदर्शन कारणों से, सूची को अद्वितीय बनाने से पहले मैं ऐसा करूँगा।

4

Collection#collectMany विधि है जो collect और फिर flatten पर कॉल करने जैसी ही काम करती है। बार ID की सूची पाने के लिए आपको क्या कर सकता:

def barIds = Foo.getAll().collectMany { it.bars*.id } 

{ it.bars*.id } बंद एक फू (मैं इन प्लेसहोल्डर नाम प्यार hehe) की बार्स की आईडी के साथ एक सूची देता है, और उसके बाद collectMany में उन सूचियों concatenates एक सूची यदि आपको अद्वितीय होने के लिए आईडी की आवश्यकता है (शायद एक बार एक से अधिक Foo से संबंधित हो सकता है), तो आप उस अभिव्यक्ति में .unique() जोड़ सकते हैं :)

संबंधित मुद्दे