हाइव फंक्शन्स: बिल्ट-इन और यूज़र डिफाइंड (UDF) उदाहरण

⚡ स्मार्ट सारांश

Hive फ़ंक्शंस को दो समूहों में बांटा जा सकता है: इंजन के साथ आने वाले बिल्ट-इन फ़ंक्शंस जो डेटा संग्रह, दिनांक, गणितीय, सशर्त, स्ट्रिंग और विविध कार्यों को कवर करते हैं, और उपयोगकर्ता द्वारा परिभाषित फ़ंक्शंस जो स्वयं लिखे गए हैं। Java Hive द्वारा उपलब्ध कराए गए तर्क के लिए।

  • 📚 छह अंतर्निहित परिवार: कलेक्शन, डेट, मैथमेटिकल, कंडीशनल, स्ट्रिंग और अन्य विविध फंक्शन सीधे HiveQL के अंदर कॉल किए जा सकते हैं।
  • 🧾 हस्ताक्षर महत्वपूर्ण हैं: प्रत्येक फ़ंक्शन में एक निश्चित तर्क सूची और एक दस्तावेजित रिटर्न प्रकार होता है, इसलिए रिटर्न प्रकार यह निर्धारित करता है कि इसका उपयोग कहाँ किया जा सकता है।
  • 🧩 यूडीएफ कमियों को पूरा करता है: जब कोई अंतर्निहित फ़ंक्शन मौजूद नहीं होता है, तो Java org.apache.hadoop.hive.ql.exec.UDF को विस्तारित करने वाली क्लास अनुपलब्ध ऑपरेशन की आपूर्ति करती है।
  • 🔢 कस्टम फ़ंक्शन के तीन स्वरूप: UDF प्रति पंक्ति एक पंक्ति लौटाता है, UDAF कई पंक्तियों को एक में समेटता है, और UDTF एक पंक्ति को कई पंक्तियों में विस्तारित करता है।
  • दो चरणों में पंजीकरण: ADD JAR कोड को क्लासपाथ पर रखता है और CREATE TEMPORARY FUNCTION क्लास को एक नाम देता है।
  • ♻️ पुन: उपयोग ही मुख्य बात है: एक परीक्षित यूडीएफ, जैसे कि स्टेमर, को हर बार फिर से लिखने के बजाय प्रत्येक क्वेरी से कॉल किया जा सकता है।

हाइव फंक्शन्स: अंतर्निर्मित और उपयोगकर्ता-परिभाषित फंक्शन्स

फ़ंक्शन विशिष्ट उद्देश्यों के लिए बनाए जाते हैं ताकि वे तालिका स्तंभ नामों के ऑपरेंड पर गणितीय, अंकगणितीय, तार्किक और संबंधपरक जैसी कार्रवाइयां कर सकें।

अंतर्निहित कार्य

ये ऐसे फ़ंक्शन हैं जो हाइव में पहले से ही उपलब्ध हैं। सबसे पहले, हमें एप्लिकेशन की आवश्यकता की जांच करनी होगी, और फिर हम अपने एप्लिकेशन में इन बिल्ट-इन फ़ंक्शन का उपयोग कर सकते हैं। हम इन फ़ंक्शन को सीधे अपने एप्लिकेशन में कॉल कर सकते हैं।

वाक्यविन्यास और प्रकार का उल्लेख अगले अनुभाग में किया गया है।

Hive में अंतर्निहित कार्यों के प्रकार:

  • संग्रहण कार्य
  • दिनांक फ़ंक्शन
  • गणितीय कार्य
  • सशर्त कार्य
  • स्ट्रिंग फ़ंक्शंस
  • विविध कार्य

नीचे इन छहों परिवारों को उनके फंक्शन सिग्नेचर और रिटर्न टाइप के साथ विस्तार से बताया गया है।

संग्रहण कार्य

इन कार्यों का उपयोग संग्रहों के लिए किया जाता है। संग्रह का अर्थ है समूह।ping ये फ़ंक्शन कई तत्वों को लौटाते हैं, और फ़ंक्शन के नाम में उल्लिखित रिटर्न प्रकार के आधार पर एक एकल तत्व या तत्वों की एक सरणी लौटाते हैं।

वापसी प्रकार फ़ंक्शन का नाम विवरण
INT आकार(मानचित्र ) यह मैप प्रकार में घटकों की संख्या प्राप्त करेगा और प्रदान करेगा।
INT आकार(सरणी ) यह ऐरे टाइप में मौजूद तत्वों की संख्या को फ़ेच करके देगा।
सरणी map_keys(मानचित्र ) यह इनपुट मैप की कुंजियों वाला एक ऐरे प्राप्त करेगा और देगा। ऐरे अव्यवस्थित है।
सरणी map_values(मानचित्र ) यह इनपुट मैप के मानों को प्राप्त करेगा और एक ऐरे देगा जिसमें मान होंगे। ऐरे अव्यवस्थित है।
सरणी सॉर्ट_एरे(एरे ) इनपुट ऐरे को उसके तत्वों के आरोही क्रम में सॉर्ट करता है और उसे लौटाता है।
बूलियन array_contains(Array , कीमत) यदि ऐरे में दूसरे आर्गुमेंट के रूप में पास किया गया मान मौजूद है तो TRUE लौटाता है।

दिनांक फ़ंक्शन

इनका उपयोग तिथियों में हेरफेर करने और तिथियों के प्रकारों को एक प्रकार से दूसरे प्रकार में परिवर्तित करने के लिए किया जाता है:

फ़ंक्शन का नाम वापसी प्रकार विवरण
यूनिक्स_टाइमस्टैम्प() BigInt हमें वर्तमान जानकारी मिल जाएगी यूनिक्स सेकंड में टाइमस्टैम्प। यह मान पूरी क्वेरी के लिए निश्चित नहीं है।
दिनांक तक (स्ट्रिंग टाइमस्टैम्प) डेटा यह टाइमस्टैम्प स्ट्रिंग के दिनांक भाग को प्राप्त करके देगा।
वर्ष(स्ट्रिंग तिथि) INT यह दिनांक या टाइमस्टैम्प स्ट्रिंग का वर्ष भाग लाएगा और देगा
तिमाही (तारीख/टाइमस्टैम्प/स्ट्रिंग) INT यह 1 से 4 की सीमा में किसी दिनांक, टाइमस्टैम्प या स्ट्रिंग के लिए वर्ष की तिमाही प्राप्त करेगा और देगा
महीना (स्ट्रिंग तिथि) INT यह किसी तारीख या टाइमस्टैम्प स्ट्रिंग का महीना वाला भाग देगा
घंटा(स्ट्रिंग दिनांक) INT यह टाइमस्टैम्प का घंटा निकालकर देगा।
मिनट(स्ट्रिंग दिनांक) INT यह टाइमस्टैम्प का मिनट निकालकर देगा।
date_sub(string प्रारंभिक तिथि, int दिन) डेटा यह सब का परिणाम प्राप्त करेगा और देगा।tracआरंभिक तिथि से कुछ दिनों की अवधि।
वर्तमान तिथि डेटा यह क्वेरी मूल्यांकन की शुरुआत में वर्तमान तिथि को प्राप्त करेगा और प्रदान करेगा।
अंतिम दिन (स्ट्रिंग तिथि) स्ट्रिंग यह उस महीने का आखिरी दिन बताएगा जिससे वह तारीख संबंधित है।
ट्रंक(स्ट्रिंग दिनांक, स्ट्रिंग प्रारूप) स्ट्रिंग यह निर्दिष्ट प्रारूप द्वारा निर्धारित इकाई तक संक्षिप्त की गई तिथि को प्राप्त करेगा और प्रदान करेगा। समर्थित प्रारूप: माह/सोम/माह, वर्ष/वर्ष/वर्ष.

गणितीय कार्य

इन फंक्शन्स का उपयोग गणितीय संक्रियाओं के लिए किया जाता है। UDF बनाने के बजाय, Hive में कुछ अंतर्निहित गणितीय फंक्शन्स मौजूद हैं।

फ़ंक्शन का नाम वापसी प्रकार विवरण
गोल (डबल एक्स) डबल यह X का राउंडेड बिगइंट मान प्राप्त करके लौटाएगा।
गोल (डबल एक्स, INT डी) डबल यह X को d दशमलव स्थानों तक पूर्णांकित करके प्राप्त करेगा और लौटाएगा।
ब्रौंड (डबल एक्स) डबल यह HALF_EVEN राउंडिंग मोड (जिसे बैंकर्स राउंडिंग भी कहा जाता है) का उपयोग करके X का राउंडेड BIGINT मान प्राप्त करेगा और लौटाएगा।
मंजिल(डबल एक्स) बिगिनट यह X मान के बराबर या उससे कम अधिकतम BIGINT मान को प्राप्त करेगा और लौटाएगा।
छत (डबल ए), छत (डबल ए) बिगिनट यह a मान के बराबर या उससे अधिक न्यूनतम BIGINT मान को खोजकर लौटाएगा।
रैंड(), रैंड(INT बीज) डबल यह 0 से 1 तक समान रूप से वितरित एक यादृच्छिक संख्या प्राप्त करेगा और लौटाएगा। सीड प्रदान करने से अनुक्रम दोहराने योग्य हो जाता है।

सशर्त कार्य

इन फंक्शनों का उपयोग सशर्त मानों की जांच के लिए किया जाता है।

फ़ंक्शन का नाम वापसी प्रकार विवरण
यदि(बूलियन परीक्षण शर्त, टी मूल्य सत्य, टी मूल्य असत्य या शून्य) T जब testCondition सही होगा तो यह valueTrue देगा, अन्यथा valueFalseOrNull देगा।
isnull(X) बूलियन यह X के NULL होने पर true और अन्यथा false मान देगा।
isnotnull(X) बूलियन यह X के NULL न होने पर true मान प्राप्त करेगा और अन्यथा false मान देगा।
nvl(T मान, T डिफ़ॉल्ट_मान) T जब मान NULL होगा तो यह default_value देगा, अन्यथा मान देगा।

स्ट्रिंग फ़ंक्शंस

स्ट्रिंग में हेरफेर और स्ट्रिंग संबंधी कार्यों को निम्नलिखित फ़ंक्शन द्वारा संभाला जाता है।

फ़ंक्शन का नाम वापसी प्रकार विवरण
रिवर्स(स्ट्रिंग X) स्ट्रिंग यह X की उलटी स्ट्रिंग देगा
rpad(स्ट्रिंग str, int लंबाई, स्ट्रिंग पैड) स्ट्रिंग यह str को पैड के साथ दाईं ओर से पैड करके कुल लंबाई तक प्राप्त करेगा।
rtrim(स्ट्रिंग X) स्ट्रिंग यह X के अंत (दाहिनी ओर) से रिक्त स्थान हटाने के बाद प्राप्त स्ट्रिंग को प्राप्त करेगा और वापस करेगा।
उदाहरण के लिये, rtrim(' परिणाम ') परिणाम ' में
स्पेस(INT n) स्ट्रिंग यह n रिक्त स्थानों वाली एक स्ट्रिंग को प्राप्त करेगा और वापस देगा।
विभाजित करें(स्ट्रिंग स्ट्र, स्ट्रिंग पैट) सरणी str को pat के चारों ओर विभाजित करता है (pat एक नियमित अभिव्यक्ति है).
str_to_map(text[, delimiter1, delimiter2]) मानचित्र यह दो विभाजकों का उपयोग करके पाठ को कुंजी-मान युग्मों में विभाजित करेगा। विभाजक 1 युग्मों को अलग करता है और विभाजक 2 प्रत्येक युग्म को विभाजित करता है।

विविध कार्य

कई अंतर्निहित फ़ंक्शन ऊपर दिए गए किसी भी श्रेणी में नहीं आते हैं। इनमें हैशिंग, सत्र की जानकारी और मनमानी कॉलिंग शामिल हैं। Java तरीकों.

फ़ंक्शन का नाम वापसी प्रकार विवरण
हैश(a1[, a2…]) INT आर्गुमेंट्स का हैश मान लौटाता है
तात्कालिक प्रयोगकर्ता() स्ट्रिंग कॉन्फ़िगर किए गए प्रमाणीकरण प्रबंधक से वर्तमान उपयोगकर्ता नाम लौटाता है
वर्तमान डेटाबेस() स्ट्रिंग वर्तमान डेटाबेस का नाम लौटाता है
md5(स्ट्रिंग/बाइनरी) स्ट्रिंग यह 128-बिट MD5 चेकसम को 32 हेक्साडेसिमल अंकों की स्ट्रिंग के रूप में लौटाता है, या NULL तर्क के लिए NULL लौटाता है।
sha1(स्ट्रिंग/बाइनरी) स्ट्रिंग यह आर्गुमेंट का SHA-1 डाइजेस्ट हेक्स स्ट्रिंग के रूप में लौटाता है।
crc32(स्ट्रिंग/बाइनरी) BigInt स्ट्रिंग या बाइनरी आर्गुमेंट का चक्रीय अतिरेक जांच मान लौटाता है।
संस्करण() स्ट्रिंग यह बिल्ड नंबर और उसके बाद बिल्ड हैश के रूप में हाइव संस्करण लौटाता है।
प्रतिबिंबित(क्लास, विधि[, तर्क1…]) बदलता रहता है कॉल करता है Java आर्गुमेंट सिग्नेचर का मिलान करके, रिफ्लेक्शन का उपयोग करके विधि। java_method() इसका पर्यायवाची है।

यूडीएफ (उपयोगकर्ता परिभाषित फ़ंक्शन)

Hive में, उपयोगकर्ता विशिष्ट ग्राहक आवश्यकताओं को पूरा करने के लिए अपने स्वयं के फ़ंक्शन परिभाषित कर सकते हैं। इन्हें Hive में UDF के रूप में जाना जाता है। उपयोगकर्ता-परिभाषित फ़ंक्शन लिखे जाते हैं। Java विशिष्ट मॉड्यूल के लिए.

कुछ यूडीएफ (UDF) विशेष रूप से एप्लिकेशन फ्रेमवर्क में कोड के पुन: उपयोग के लिए डिज़ाइन किए गए हैं। डेवलपर इन फ़ंक्शंस को लिखता है। Java और उन यूडीएफ को हाइव के साथ एकीकृत करता है।

क्वेरी निष्पादन के दौरान, डेवलपर सीधे कोड का उपयोग कर सकता है, और यूडीएफ उपयोगकर्ता द्वारा परिभाषित कार्यों के अनुसार आउटपुट लौटाएगा। यह कोडिंग और निष्पादन के मामले में उच्च प्रदर्शन प्रदान करता है।

उदाहरण के लिए, स्ट्रिंग स्टेमिंग के लिए हाइव में कोई पूर्वनिर्धारित फ़ंक्शन नहीं है। इसके लिए, हम एक स्टेम यूडीएफ लिख सकते हैं। Javaजहां भी हमें स्टेम कार्यक्षमता की आवश्यकता होती है, हम हाइव में इस स्टेम यूडीएफ को सीधे कॉल कर सकते हैं।

यहां स्टेमिंग फ़ंक्शनैलिटी का अर्थ है मूल शब्दों से नए शब्द बनाना। एक स्टेमिंग एल्गोरिदम "wishing", "wished" और "wishes" शब्दों को मूल शब्द "wish" में बदल देता है। इस प्रकार की कार्यक्षमता को पूरा करने के लिए, हम एक UDF लिख सकते हैं। Java और इसे एकीकृत करें करंड.

उपयोग के आधार पर, यूडीएफ को अलग-अलग संख्या में इनपुट और आउटपुट मान स्वीकार करने और उत्पन्न करने के लिए लिखा जा सकता है।

सामान्य प्रकार का यूडीएफ एक इनपुट मान स्वीकार करता है और एक आउटपुट मान उत्पन्न करता है। यदि यूडीएफ का उपयोग किसी क्वेरी में किया जाता है, तो परिणाम डेटा सेट की प्रत्येक पंक्ति के लिए यूडीएफ को एक बार कॉल किया जाएगा।

दूसरी ओर, एक फ़ंक्शन इनपुट के रूप में मानों का एक समूह स्वीकार कर सकता है और एक एकल आउटपुट मान भी लौटा सकता है। यही अंतर आगे वर्णित तीन प्रकार के कस्टम फ़ंक्शन को अलग करता है।

हाइव में UDF बनाम UDAF बनाम UDTF

Hive में कस्टम फ़ंक्शंस को इनपुट और आउटपुट पंक्तियों की संख्या के आधार पर वर्गीकृत किया जाता है। गलत टाइप का चयन करना सबसे आम कारण है कि कोई कस्टम फ़ंक्शन कंपाइल होने से इनकार कर देता है या अपेक्षित टेबल के स्थान पर केवल एक पंक्ति लौटाता है।

प्रकार पंक्तियाँ अंदर → पंक्तियाँ बाहर कक्षा का विस्तार करने के लिए अंतर्निर्मित उदाहरण
यूडीएफ एक पंक्ति → एक पंक्ति org.apache.hadoop.hive.ql.exec.UDF लंबाई(), गोल(), उल्टा()
यूडीएएफ अनेक पंक्तियाँ → एक पंक्ति org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver गणना(), न्यूनतम(), अधिकतम()
यूडीटीएफ एक पंक्ति → अनेक पंक्तियाँ org.apache.hadoop.hive.ql.udf.generic.GenericUDTF explode(), json_tuple(), parse_url_tuple()

इस तालिका से दो व्यावहारिक नियम निकलते हैं:

  • एक UDAF को लगभग हमेशा GROUP BY क्लॉज़ के साथ जोड़ा जाता है, क्योंकि यह प्रत्येक समूह को एक पंक्ति में समेट देता है।
  • एक UDTF को एक ही SELECT सूची में अन्य कॉलम के साथ नहीं चुना जा सकता है, इसलिए इसका उपयोग आमतौर पर LATERAL VIEW के साथ किया जाता है।

पंक्ति-स्तर के कार्य के लिए एक दूसरा, अधिक सक्षम आधार वर्ग भी है, जिसे GenericUDF कहा जाता है, जो सरणियों, मानचित्रों और संरचनाओं जैसे जटिल प्रकारों और चर संख्या में तर्कों को स्वीकार करता है।

Hive में UDF कैसे लिखें और रजिस्टर करें

ऊपर वर्णित मूल उदाहरण को चार चरणों में एक वास्तविक फ़ंक्शन के रूप में बनाया जा सकता है। इससे आगे कुछ भी नहीं। Java इसके लिए कंपाइलर और एक चालू हाइव सेशन की आवश्यकता होती है।

चरण 1) लिखना एक Java यह एक क्लास है जो UDF को एक्सटेंड करती है और एक पब्लिक evaluate() मेथड को इम्प्लीमेंट करती है। Hive प्रत्येक पंक्ति के लिए evaluate() मेथड को एक बार कॉल करता है, इसलिए इस मेथड को NULL इनपुट को हैंडल करना आना चाहिए।

package com.guru99.hive.udf;

import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;

public final class Stem extends UDF {

    public Text evaluate(final Text input) {
        if (input == null) {
            return null;
        }
        String word = input.toString().toLowerCase();
        if (word.endsWith("ing")) {
            word = word.substring(0, word.length() - 3);
        } else if (word.endsWith("ed") || word.endsWith("es")) {
            word = word.substring(0, word.length() - 2);
        }
        return new Text(word);
    }
}

चरण 2) क्लास को कंपाइल करें और इसे उन सभी क्लासों के साथ एक JAR फ़ाइल में पैक करें जिन पर यह निर्भर करता है, उदाहरण के लिए hive-udf-1.0.jar।

चरण 3) JAR फ़ाइल को Hive क्लासपाथ पर रखें और क्लास के साथ एक फ़ंक्शन नाम जोड़ें। एक अस्थायी फ़ंक्शन केवल वर्तमान सत्र के लिए ही सक्रिय रहता है।

ADD JAR /home/hduser/hive-udf-1.0.jar;

CREATE TEMPORARY FUNCTION stem AS 'com.guru99.hive.udf.Stem';

चरण 4) इस नए फ़ंक्शन को ठीक उसी तरह कॉल करें जैसे किसी बिल्ट-इन फ़ंक्शन को करते हैं। "wishing", "wished" और "wishes" शब्दों पर लागू करने पर, यह क्लास तीनों के लिए "wish" लौटाती है।

SELECT word, stem(word) FROM words;

इस फ़ंक्शन को हर सेशन और हर उपयोगकर्ता के लिए उपलब्ध रखने के लिए, इसे डेटाबेस के साथ स्थायी रूप से पंजीकृत करें। JAR फ़ाइल ऐसे पथ पर होनी चाहिए जिसे पूरा क्लस्टर पढ़ सके, जो आमतौर पर HDFS होता है।

CREATE FUNCTION default.stem AS 'com.guru99.hive.udf.Stem'
USING JAR '/user/hive/udfs/hive-udf-1.0.jar';

एक ही क्लास में एक से अधिक evaluate() मेथड घोषित किए जा सकते हैं। Hive आर्गुमेंट सिग्नेचर के आधार पर कॉल का मिलान करता है, इसी वजह से एक फंक्शन स्ट्रिंग और इंटीजर दोनों को स्वीकार कर सकता है।

अक्सर पूछे जाने वाले प्रश्न

SHOW FUNCTIONS पंजीकृत सभी नामों को सूचीबद्ध करता है, जिनमें कस्टम नाम भी शामिल हैं। DESCRIBE FUNCTION name एक पंक्ति का हस्ताक्षर प्रिंट करता है, और DESCRIBE FUNCTION EXTENDED name उन उपयोग उदाहरणों को जोड़ता है जहां कार्यान्वयन वर्ग उन्हें प्रदान करता है।

लगभग हमेशा नाम या स्कोप की समस्या होती है: AS के बाद की स्ट्रिंग पूरी तरह से योग्य क्लास नाम होनी चाहिए, और ADD JAR केवल उसी सेशन पर लागू होता है जिसने इसे चलाया था। दोबारा कनेक्ट करने पर JAR और कोई भी अस्थायी फ़ंक्शन दोनों हट जाते हैं।

GenericUDF का उपयोग तब करें जब फ़ंक्शन जटिल प्रकार जैसे कि ऐरे, मैप या स्ट्रक्चर लेता हो, कई आर्गुमेंट लेता हो, या आर्गुमेंट प्रकारों को स्वयं मान्य करने की आवश्यकता हो। सरल UDF क्लास रिफ्लेक्शन द्वारा प्रकारों को हल करती है और केवल प्रिमिटिव राइटेबल को ही हैंडल करती है।

एक वास्तविक UDF को JVM पर चलना चाहिए। अन्य भाषाओं के लिए, करंड यह TRANSFORM क्लॉज़ प्रदान करता है, जो प्रत्येक पंक्ति को किसी बाहरी स्क्रिप्ट जैसे कि के माध्यम से स्ट्रीम करता है। Python मानक इनपुट और आउटपुट पर। यह धीमा है लेकिन इससे बचा जा सकता है। Java पूरी तरह से।

वे ऐसा कर सकते हैं। evaluate() फ़ंक्शन प्रति पंक्ति एक बार चलता है, इसलिए जटिल लॉजिक पंक्तियों की संख्या से गुणा हो जाता है, और विधि के अंदर ऑब्जेक्ट आवंटन से गार्बेज-कलेक्शन पर दबाव बढ़ता है। यदि कोई अंतर्निहित फ़ंक्शन मौजूद हो तो उसे प्राथमिकता दें, और evaluate() को इनपुट/आउटपुट से मुक्त रखें।

नहीं। फ़ंक्शन के नाम केस-इनसेसिटिव होते हैं, इसलिए ROUND(), Round() और round() एक ही फ़ंक्शन हैं। Java AS क्लॉज़ में क्लास का नाम एक अलग मामला है और इसे संकलित क्लास से बिल्कुल मेल खाना चाहिए, जिसमें उसका पैकेज भी शामिल है।

मशीन लर्निंग सहायक सरल भाषा में दिए गए विवरण को संभावित हस्ताक्षरों से जोड़ते हैं और चेतावनी देते हैं कि रिटर्न टाइप लक्ष्य कॉलम के अनुरूप नहीं है। सुझाव को प्रमाणित हस्ताक्षर से सत्यापित करें, क्योंकि उत्पन्न नाम कभी-कभी किसी अन्य SQL भाषा से संबंधित होते हैं।

यह ऑपरेशन का वर्णन करने वाली टिप्पणी से एक उपयोगी ढांचा तैयार करता है — जिसमें क्लास डिक्लेरेशन, इम्पोर्ट्स और एक evaluate() मेथड शामिल हैं। नल हैंडलिंग, राइटेबल टाइप्स और पैकेजिंग स्टेप की अभी भी समीक्षा की आवश्यकता है, और फंक्शन को वास्तविक पंक्तियों पर टेस्ट किया जाना चाहिए।

इस पोस्ट को संक्षेप में इस प्रकार लिखें: