ORM बढ़िया हैं, जब तक कि वे रिसाव . सब करते हैं, आखिरकार। Ecto युवा है (अर्थात, इसने केवल OR
. की क्षमता प्राप्त की है जहां क्लॉज एक साथ 30 दिन पहले
), इसलिए यह पर्याप्त रूप से परिपक्व नहीं है कि एक एपीआई विकसित किया है जो उन्नत SQL gyrations पर विचार करता है।
संभावित विकल्पों का सर्वेक्षण करते हुए, आप अनुरोध में अकेले नहीं हैं। टुकड़ों में सूचियों को समझने में असमर्थता (चाहे order_by
. के भाग के रूप में हो या where
या कहीं और) का उल्लेख Ecto अंक #1485
में किया गया है , StackOverflow
पर , एलिक्सिर फोरम पर
और यह ब्लॉग पोस्ट
. बाद वाला विशेष शिक्षाप्रद है। थोड़े समय में इस पर और अधिक। पहले, आइए कुछ प्रयोग करके देखें।
प्रयोग #1: कोई पहले Kernel.apply/3
का उपयोग करके देख सकता है सूची को fragment
. पास करने के लिए , लेकिन वह काम नहीं करेगा:
|> order_by(Kernel.apply(Ecto.Query.Builder, :fragment, ^ids))
प्रयोग #2: तब शायद हम इसे स्ट्रिंग मैनिपुलेशन के साथ बना सकते हैं। fragment
देने के बारे में कैसे? एक स्ट्रिंग बिल्ट-एट-रनटाइम जिसमें पर्याप्त प्लेसहोल्डर होते हैं ताकि वह सूची से बाहर निकल सके:
|> order_by(fragment(Enum.join(["FIELD(id,", Enum.join(Enum.map(ids, fn _ -> "?" end), ","), ")"], ""), ^ids))
जो FIELD(id,?,?,?)
. उत्पन्न करेगा दिया गया ids = [1, 2, 3]
. नहीं, यह भी काम नहीं करता।
प्रयोग #3: आईडी से निर्मित संपूर्ण, अंतिम एसक्यूएल बनाना, कच्चे आईडी मानों को सीधे कंपोज्ड स्ट्रिंग में रखना। भयानक होने के अलावा, यह भी काम नहीं करता:
|> order_by(fragment(Enum.join(["FIELD(id,", Enum.join(^ids, ","), ")"], "")))
प्रयोग #4: यह मुझे उस ब्लॉग पोस्ट के बारे में बताता है जिसका मैंने उल्लेख किया था। इसमें लेखक or_where
. की कमी को हैक कर लेता है एक साथ खींचने के लिए शर्तों की संख्या के आधार पर पूर्व-निर्धारित मैक्रोज़ के एक सेट का उपयोग करना:
defp orderby_fragment(query, [v1]) do
from u in query, order_by: fragment("FIELD(id,?)", ^v1)
end
defp orderby_fragment(query, [v1,v2]) do
from u in query, order_by: fragment("FIELD(id,?,?)", ^v1, ^v2)
end
defp orderby_fragment(query, [v1,v2,v3]) do
from u in query, order_by: fragment("FIELD(id,?,?,?)", ^v1, ^v2, ^v3)
end
defp orderby_fragment(query, [v1,v2,v3,v4]) do
from u in query, order_by: fragment("FIELD(id,?,?,?)", ^v1, ^v2, ^v3, ^v4)
end
हालांकि यह काम करता है और "अनाज के साथ" ओआरएम का उपयोग करता है, इसलिए इसके लिए आवश्यक है कि आपके पास उपलब्ध फ़ील्ड की सीमित, प्रबंधनीय संख्या हो। यह गेम चेंजर हो भी सकता है और नहीं भी।
मेरी सिफारिश:ओआरएम के लीक के आसपास हथकंडा करने की कोशिश मत करो। आप सबसे अच्छी क्वेरी जानते हैं। अगर ओआरएम इसे स्वीकार नहीं करेगा, तो इसे सीधे कच्चे एसक्यूएल के साथ लिखें, और दस्तावेज क्यों ओआरएम काम नहीं करता है। इसे किसी फ़ंक्शन या मॉड्यूल के पीछे ढालें ताकि आप इसके कार्यान्वयन को बदलने का भविष्य का अधिकार सुरक्षित रख सकें। एक दिन, जब ओआरएम पकड़ में आता है, तो आप इसे बाकी सिस्टम पर बिना किसी प्रभाव के अच्छी तरह से फिर से लिख सकते हैं।