Restful API में कई-से-कई रिश्तों को कैसे संभालना है?


288

कल्पना कीजिए कि आपके पास 2 संस्थाएं हैं, खिलाड़ी और टीम , जहां खिलाड़ी कई टीमों में हो सकते हैं। मेरे डेटा मॉडल में, मेरे पास प्रत्येक इकाई के लिए एक तालिका है, और रिश्तों को बनाए रखने के लिए एक सम्मिलित तालिका है। हाइबरनेट इसे संभालने में ठीक है, लेकिन मैं एक रिस्टफुल एपीआई में इस संबंध को कैसे उजागर कर सकता हूं?

मैं कुछ तरीके सोच सकता हूं। सबसे पहले, मेरे पास प्रत्येक इकाई में दूसरे की एक सूची हो सकती है, इसलिए एक प्लेयर ऑब्जेक्ट में टीमों की एक सूची होगी, और प्रत्येक टीम ऑब्जेक्ट में उन खिलाड़ियों की सूची होगी जो इसके हैं। एक खिलाड़ी को एक टीम में जोड़ने के लिए, आप अनुरोध के पेलोड के रूप में उपयुक्त वस्तु के साथ POST /playerया POST जैसी किसी चीज के लिए खिलाड़ी के प्रतिनिधित्व को केवल POST /teamकरेंगे। यह मेरे लिए सबसे "रेस्टफुल" लगता है लेकिन थोड़ा अजीब लगता है।

/api/team/0:

{
    name: 'Boston Celtics',
    logo: '/img/Celtics.png',
    players: [
        '/api/player/20',
        '/api/player/5',
        '/api/player/34'
    ]
}

/api/player/20:

{
    pk: 20,
    name: 'Ray Allen',
    birth: '1975-07-20T02:00:00Z',
    team: '/api/team/0'
}

जिस तरह से मैं ऐसा करने के लिए सोच सकता हूं वह अपने आप में एक संसाधन के रूप में रिश्ते को उजागर करना होगा। इसलिए किसी दिए गए टीम के सभी खिलाड़ियों की सूची देखने के लिए, आप एक GET /playerteam/team/{id}या ऐसा कुछ कर सकते हैं और PlayerTeam संस्थाओं की सूची वापस पा सकते हैं। एक खिलाड़ी को एक टीम में जोड़ने के लिए, /playerteamपेलोड के रूप में एक उचित रूप से निर्मित प्लेयरटेम इकाई के साथ POST ।

/api/team/0:

{
    name: 'Boston Celtics',
    logo: '/img/Celtics.png'
}

/api/player/20:

{
    pk: 20,
    name: 'Ray Allen',
    birth: '1975-07-20T02:00:00Z',
    team: '/api/team/0'
}

/api/player/team/0/:

[
    '/api/player/20',
    '/api/player/5',
    '/api/player/34'        
]

इसके लिए सबसे अच्छा अभ्यास क्या है?

जवाबों:


129

एक RESTful इंटरफ़ेस में, आप उन रिश्तों को लिंक के रूप में एन्कोडिंग करके संसाधनों के बीच संबंधों का वर्णन करने वाले दस्तावेज़ वापस कर सकते हैं। इस प्रकार, एक टीम को एक दस्तावेज संसाधन ( /team/{id}/players) कहा जा सकता है जो टीम के खिलाड़ियों ( /player/{id}) के लिंक की एक सूची है , और एक खिलाड़ी के पास एक दस्तावेज संसाधन हो सकता है (/player/{id}/teams) कि टीमों के लिंक की एक सूची है कि खिलाड़ी का एक सदस्य है। अच्छा और सममित। आप उस सूची पर मानचित्र संचालन आसानी से कर सकते हैं, यहां तक ​​कि एक रिश्ते को अपनी खुद की आईडी भी दे सकते हैं (यकीनन उनके पास दो आईडी होगी, यह इस बात पर निर्भर करता है कि आप संबंध टीम-पहले या खिलाड़ी-पहले के बारे में सोच रहे हैं) अगर यह आसान हो जाता है । केवल मुश्किल बिट यह है कि आपको दूसरे छोर से संबंध को हटाने के लिए याद रखना है, साथ ही यदि आप इसे एक छोर से हटाते हैं, लेकिन एक अंतर्निहित डेटा मॉडल का उपयोग करके इसे सख्ती से संभालना और फिर REST इंटरफ़ेस का एक दृश्य होना उस मॉडल को आसान बनाने जा रहा है।

रिश्ता आईडी शायद UUIDs या कुछ समान रूप से लंबे और यादृच्छिक पर आधारित होना चाहिए, चाहे जो भी प्रकार की ID आप टीमों और खिलाड़ियों के लिए उपयोग करें। यही कारण है कि आप टकरावों के बारे में चिंता किए बिना रिश्ते के प्रत्येक छोर के लिए आईडी घटक के रूप में एक ही यूयूआईडी का उपयोग करेंगे (छोटे पूर्णांकों का वह लाभ नहीं है)। यदि इन सदस्यता संबंधों में नंगे तथ्य के अलावा कोई गुण है कि वे एक खिलाड़ी और एक टीम को एक द्विदिश फैशन में संबंधित करते हैं, तो उनकी अपनी पहचान होनी चाहिए जो खिलाड़ियों और टीमों दोनों से स्वतंत्र हो; खिलाड़ी पर एक GET »टीम दृश्य ( /player/{playerID}/teams/{teamID}) तब एक HTTP रीडायरेक्शनल दृश्य ( /memberships/{uuid}) को पुनर्निर्देशित कर सकता है ।

मैं आपके द्वारा दिए गए किसी भी XML दस्तावेज़ में लिंक लिखने की सलाह देता हूं (यदि आप XML का उत्पादन करते हैं तो) XLink xlink:href विशेषताओं का उपयोग करके ।


265

/memberships/संसाधनों का एक अलग सेट बनाएं ।

  1. बाकी अगर कुछ और नहीं है तो यह बेकार सिस्टम बनाने के बारे में है। इस समय, आप केवल दिलचस्पी होती है कि किसी दिए गए खिलाड़ी किसी दिए गए टीम पर है, लेकिन भविष्य में कुछ बिंदु पर, आप होगा अधिक डेटा के साथ उस रिश्ते पर टिप्पणी करना चाहते हैं: कितनी देर तक वे उस टीम पर किया गया है, जो उन्हें संदर्भित किया उस टीम के लिए, जो उनका कोच है / उस टीम आदि के समय था।
  2. आरईएसटी दक्षता के लिए कैशिंग पर निर्भर करता है, जिसके लिए कैश एटमॉसिटी और अमान्यकरण के लिए कुछ विचार की आवश्यकता होती है। यदि आप /teams/3/players/उस सूची में एक नई इकाई पोस्ट करते हैं तो उसे अमान्य कर दिया जाएगा, लेकिन आप नहीं चाहते कि वैकल्पिक URL /players/5/teams/कैश किया जाए। हां, अलग-अलग कैश में अलग-अलग उम्र के साथ प्रत्येक सूची की प्रतियां होंगी, और हम इसके बारे में बहुत कुछ नहीं कर सकते हैं, लेकिन हम कम से कम उपयोगकर्ता के लिए भ्रम को कम कर सकते हैं अपडेट को उन संस्थाओं की संख्या को सीमित करके जिन्हें हमें अमान्य करने की आवश्यकता है अपने ग्राहक के स्थानीय कैश में एक और केवल एक पर /memberships/98745( अधिक विस्तृत चर्चा के लिए वितरित लेन-देन से परे जीवन में "वैकल्पिक सूचकांकों की हेलेंड की चर्चा" देखें )।
  3. आप उपरोक्त 2 बिंदुओं को केवल चुनकर /players/5/teamsया /teams/3/players(लेकिन दोनों नहीं) लागू कर सकते हैं । चलो पूर्व मान लेते हैं। कुछ बिंदु पर, हालांकि, आप वर्तमान सदस्यता /players/5/teams/की सूची के लिए आरक्षित करना चाहेंगे , और फिर भी कहीं न कहीं पिछली सदस्यता का उल्लेख करने में सक्षम होंगे । संसाधनों के लिए हाइपरलिंक्स की एक सूची बनाएं , और फिर आप जब चाहें तब जोड़ सकते हैं , व्यक्तिगत सदस्यता संसाधनों के लिए हर किसी के बुकमार्क को तोड़ने के बिना। यह एक सामान्य अवधारणा है; मुझे यकीन है कि आप अन्य समान वायदा की कल्पना कर सकते हैं जो आपके विशिष्ट मामले पर अधिक लागू होते हैं।/players/5/memberships//memberships/{id}//players/5/past_memberships/

11
बिंदु 1 और 2 को पूरी तरह से समझाया गया है, धन्यवाद, अगर किसी के पास वास्तविक जीवन के अनुभव में बिंदु 3 के लिए अधिक मांस है, तो इससे मुझे मदद मिलेगी।
एलेन

2
सबसे अच्छा और सरल जवाब IMO धन्यवाद! दो एंडपॉइंट होने और उन्हें सिंक में रखने के बाद जटिलताओं का एक मेजबान होता है।
वेंकट डी।

7
हाय फुमानु। प्रश्न: बाकी समापन बिंदु / सदस्यता / 98745 में url के अंत में वह संख्या क्या दर्शाती है? क्या यह सदस्यता के लिए एक अद्वितीय आईडी है? सदस्यता के समापन बिंदु के साथ कोई कैसे सहभागिता करेगा? एक खिलाड़ी को जोड़ने के लिए एक POST भेजा जाएगा जिसमें पेलोड {दल: 3, खिलाड़ी: 6} के साथ होगा, जिससे दोनों के बीच की कड़ी बनेगी? एक GET के बारे में क्या? क्या आप परिणाम प्राप्त करने के लिए / सदस्यता के लिए एक खिलाड़ी भेजेंगे? खिलाड़ी = और / सदस्यता? टीम =? यह विचार है? क्या मुझे कुछ याद आ रहा है? (मैं आराम करने वाले समापन बिंदुओं को सीखने की कोशिश कर रहा हूं) क्या इस मामले में, सदस्यता / 98745 में आईडी 98745 वास्तव में उपयोगी है?
अरुवु

@ एक बार एसोसिएशन के लिए एक अलग समापन बिंदु एक सरोगेट पीके के साथ प्रदान किया जाना चाहिए। यह जीवन को सामान्य रूप से बहुत आसान बनाता है: / सदस्यता / {सदस्यताआई}। कुंजी (playerId, teamId) अद्वितीय बनी हुई है और इस प्रकार इस संबंध को रखने वाले संसाधनों पर उपयोग किया जा सकता है: / टीमों / {teamId} / खिलाड़ियों और / खिलाड़ियों / {playerId} / टीमों। लेकिन यह हमेशा नहीं होता है जब दोनों तरफ इस तरह के संबंध बने रहते हैं। उदाहरण के लिए, व्यंजनों और सामग्री: आप शायद ही कभी / सामग्री / {संघटक /} / व्यंजनों / का उपयोग करने की आवश्यकता होगी।
अलेक्जेंडर पालमार्चुक

65

मैं उप-संसाधनों, सामान्य डिजाइन / ट्रैवर्सल के साथ इस तरह के संबंध का मानचित्र बनाऊंगा:

# team resource
/teams/{teamId}

# players resource
/players/{playerId}

# teams/players subresource
/teams/{teamId}/players/{playerId}

रेस्टफुल-टर्म्स में यह SQL और जॉइन के बारे में नहीं बल्कि कलेक्शन, सब-कलेक्शन और ट्रैवर्सल में ज्यादा मदद करता है।

कुछ उदाहरण:

# getting player 3 who is on team 1
# or simply checking whether player 3 is on that team (200 vs. 404)
GET /teams/1/players/3

# getting player 3 who is also on team 3
GET /teams/3/players/3

# adding player 3 also to team 2
PUT /teams/2/players/3

# getting all teams of player 3
GET /players/3/teams

# withdraw player 3 from team 1 (appeared drunk before match)
DELETE /teams/1/players/3

# team 1 found a replacement, who is not registered in league yet
POST /players
# from payload you get back the id, now place it officially to team 1
PUT /teams/1/players/44

जैसा कि आप देखते हैं कि मैं खिलाड़ियों को टीमों में रखने के लिए POST का उपयोग नहीं करता, लेकिन PUT, जो आपके n: n खिलाड़ियों और टीमों के संबंधों को बेहतर तरीके से संभालता है।


20
क्या होगा अगर टीम_प्लेयर को स्टेटस आदि की अतिरिक्त जानकारी हो? हम इसे आपके मॉडल में कहाँ दर्शाते हैं? क्या हम इसे एक संसाधन के लिए बढ़ावा दे सकते हैं, और इसके लिए URL प्रदान कर सकते हैं, जैसे खेल /, खिलाड़ी /
नरेंद्र कम्मा

अरे, त्वरित प्रश्न बस यह सुनिश्चित करने के लिए कि मुझे यह अधिकार मिल रहा है: GET / टीमों / 1 / खिलाड़ियों / 3 एक खाली प्रतिक्रिया निकाय देता है। इस से केवल सार्थक प्रतिक्रिया 200 बनाम 404 है। खिलाड़ी इकाई की जानकारी (नाम, आयु, आदि) GET / टीमों / 1 / खिलाड़ियों / 3 द्वारा वापस नहीं की जाती है। यदि ग्राहक खिलाड़ी के बारे में अतिरिक्त जानकारी प्राप्त करना चाहता है, तो उसे GET / खिलाड़ियों / 3 प्राप्त करना होगा। क्या यह सब सही है?
वरदगन

2
मैं आपकी मैपिंग से सहमत हूं, लेकिन एक सवाल है। यह व्यक्तिगत राय की बात है, लेकिन आप POST / टीमों / 1 / खिलाड़ियों के बारे में क्या सोचते हैं और आप इसका उपयोग क्यों नहीं करते हैं? क्या आपको इस दृष्टिकोण में कोई असुविधा / भ्रामकता दिखाई देती है?
JakubKnejzlik 5

2
POST एक आदर्श नहीं है, अर्थात यदि आप POST / टीमों / 1 / खिलाड़ियों को n-बार करते हैं, तो आप n-times / टीमों / 1 को बदल देंगे। लेकिन एक खिलाड़ी को / टीमों / 1 n-बार में ले जाने से टीम की स्थिति नहीं बदलेगी, इसलिए PUT का उपयोग करना अधिक स्पष्ट है।
मैनुअल अलादाना

1
@ नरेन्द्रकम्मा मुझे लगता है कि statusPUT अनुरोध में केवल परम के रूप में भेजूं ? क्या उस दृष्टिकोण के लिए एक नकारात्मक पहलू है?
ट्रैक्सो

22

मौजूदा उत्तरों में संगति और निष्क्रियता की भूमिकाओं की व्याख्या नहीं की गई है - जो UUIDsआईडी के PUTबजाय / के लिए / यादृच्छिक संख्या की उनकी सिफारिशों को प्रेरित करती हैं POST

यदि हम उस मामले पर विचार करते हैं जहां हमारे पास एक सरल परिदृश्य है जैसे " एक टीम में एक नया खिलाड़ी जोड़ें ", तो हम स्थिरता के मुद्दों का सामना करते हैं।

क्योंकि खिलाड़ी मौजूद नहीं है, हमें इसकी आवश्यकता है:

POST /players { "Name": "Murray" } //=> 302 /players/5
POST /teams/1/players/5

हालांकि, ग्राहक ऑपरेशन के बाद विफल POSTकरने के लिए /players, हम एक खिलाड़ी है कि एक टीम का नहीं है बना लिया है:

POST /players { "Name": "Murray" } //=> 302 /players/5
// *client failure*
// *client retries naively*
POST /players { "Name": "Murray" } //=> 302 /players/6
POST /teams/1/players/6

अब हमारे पास एक अनाथ डुप्लिकेट खिलाड़ी है /players/5

इसे ठीक करने के लिए हम कस्टम रिकवरी कोड लिख सकते हैं जो अनाथ खिलाड़ियों के लिए जांचता है जो कुछ प्राकृतिक कुंजी (जैसे Name) से मेल खाते हैं । यह कस्टम कोड है जिसका परीक्षण करने की आवश्यकता है, अधिक पैसा और समय आदि

कस्टम रिकवरी कोड की आवश्यकता से बचने के लिए, हम PUTइसके बजाय लागू कर सकते हैं POST

से आरएफसी :

की मंशा PUTहै

एक ऑपरेशन के लिए एक आदर्श होना चाहिए, इसे बाहरी डेटा जैसे सर्वर-जनरेट किए गए आईडी अनुक्रमों को बाहर करना होगा। यही कारण है कि लोग एक साथ दोनों के लिए PUTऔर UUIDएस की सिफारिश कर रहे Idहैं।

यह हमें /players PUTऔर /memberships PUTपरिणाम दोनों के बिना पुनर्मिलन करने की अनुमति देता है :

PUT /players/23lkrjrqwlej { "Name": "Murray" } //=> 200 OK
// *client failure*
// *client YOLOs*
PUT /players/23lkrjrqwlej { "Name": "Murray" } //=> 200 OK
PUT /teams/1/players/23lkrjrqwlej

सब कुछ ठीक है और हमें आंशिक विफलताओं के लिए पुन: प्रयास करने से अधिक कुछ करने की आवश्यकता नहीं थी।

यह मौजूदा उत्तरों का एक परिशिष्ट है, लेकिन मुझे आशा है कि यह उन्हें इस बात की बड़ी तस्वीर के संदर्भ में बताता है कि कितना लचीला और विश्वसनीय ReST हो सकता है।


इस काल्पनिक समापन में, आपको कहां 23lkrjrqwlejसे मिला?
cccoutinho

1
कीबोर्ड पर चेहरा रोल - 23lkr के बारे में कुछ खास नहीं है ... gobbledegook अन्य कि यह अनुक्रमिक या सार्थक नहीं है
सेठ

9

मेरे वरीय समाधान तीन संसाधनों बनाने के लिए है: Players, Teamsऔर TeamsPlayers

इसलिए, एक टीम के सभी खिलाड़ियों को प्राप्त करने के लिए, बस Teamsसंसाधन पर जाएं और कॉल करके अपने सभी खिलाड़ियों को प्राप्त करें GET /Teams/{teamId}/Players

दूसरी ओर, सभी टीमों को एक खिलाड़ी के खेलने के लिए Teamsसंसाधन प्राप्त करें Players। पुकारते हैं GET /Players/{playerId}/Teams

और, कई-से-कई संबंध कॉल करने के लिए GET /Players/{playerId}/TeamsPlayersया GET /Teams/{teamId}/TeamsPlayers

ध्यान दें, इस समाधान में, जब आप कॉल करते हैं, तो आपको संसाधनों GET /Players/{playerId}/Teamsकी एक सरणी मिलती है Teams, ठीक उसी तरह का संसाधन जब आप कॉल करते हैं GET /Teams/{teamId}। रिवर्स उसी सिद्धांत का पालन करता है, आपको Playersकॉल करते समय संसाधनों की एक सरणी मिलती है GET /Teams/{teamId}/Players

किसी भी कॉल में, रिश्ते के बारे में कोई जानकारी नहीं दी जाती है। उदाहरण के लिए, कोई contractStartDateलौटाया नहीं गया है, क्योंकि लौटाए गए संसाधन में संबंध के बारे में कोई जानकारी नहीं है, केवल अपने स्वयं के संसाधन के बारे में।

Nn संबंध से निपटने के लिए, GET /Players/{playerId}/TeamsPlayersया तो कॉल करें GET /Teams/{teamId}/TeamsPlayers। ये कॉल, बिल्कुल संसाधन वापसी TeamsPlayers

इस TeamsPlayersसंसाधन है id, playerId, teamIdगुण, साथ ही कुछ अन्य लोगों के संबंध का वर्णन करने के लिए। साथ ही, इससे निपटने के लिए आवश्यक तरीके हैं। GET, POST, PUT, DELETE आदि जो वापस लौटेंगे, शामिल होंगे, अपडेट करेंगे, रिलेशनशिप रिसोर्स को हटाएंगे।

TeamsPlayersसंसाधन औजार कुछ प्रश्नों, की तरह GET /TeamsPlayers?player={playerId}सब वापस जाने के लिए TeamsPlayersरिश्तों खिलाड़ी द्वारा की पहचान {playerId}की है। एक ही विचार के बाद, टीम में खेले गए GET /TeamsPlayers?team={teamId}सभी को वापस करने के लिए उपयोग करें । या तो कॉल में, संसाधन वापस आ गया है। रिश्ते से संबंधित सभी डेटा वापस कर दिया जाता है।TeamsPlayers{teamId}GETTeamsPlayers

कॉल करते समय GET /Players/{playerId}/Teams(या GET /Teams/{teamId}/Players), संसाधन Players(या Teams) TeamsPlayersसंबंधित टीमों (या खिलाड़ियों) को एक क्वेरी फ़िल्टर का उपयोग करके वापस करने के लिए कहता है।

GET /Players/{playerId}/Teams इस तरह काम करता है:

  1. सभी टीमों को खोजें कि खिलाड़ी के पास आईडी = खिलाड़ी है । ( GET /TeamsPlayers?player={playerId})
  2. लौटे हुए टीम्सपेलर्स को लूप करें
  3. का उपयोग करते हुए teamId से प्राप्त TeamsPlayers , कॉल GET /Teams/{teamId}और लौट आए डाटा स्टोर
  4. लूप खत्म होने के बाद। उन सभी टीमों को लौटाएं जो लूप में मिली थीं।

आप सभी एल्गोरिदम का उपयोग किसी टीम के सभी खिलाड़ियों को कॉल करने के लिए कर सकते हैं GET /Teams/{teamId}/Players, लेकिन टीम और खिलाड़ियों का आदान-प्रदान कर सकते हैं।

मेरे संसाधन इस तरह दिखेंगे:

/api/Teams/1:
{
    id: 1
    name: 'Vasco da Gama',
    logo: '/img/Vascao.png',
}

/api/Players/10:
{
    id: 10,
    name: 'Roberto Dinamite',
    birth: '1954-04-13T00:00:00Z',
}

/api/TeamsPlayers/100
{
    id: 100,
    playerId: 10,
    teamId: 1,
    contractStartDate: '1971-11-25T00:00:00Z',
}

यह समाधान केवल REST संसाधनों पर निर्भर करता है। हालाँकि खिलाड़ियों, टीमों या उनके संबंधों से डेटा प्राप्त करने के लिए कुछ अतिरिक्त कॉल आवश्यक हो सकते हैं, लेकिन सभी HTTP तरीके आसानी से लागू हो जाते हैं। POST, PUT, DELETE सरल और सीधे हैं।

जब भी कोई संबंध बनाया जाता है, तो अपडेट किया जाता है या हटा दिया जाता है, दोनों Playersऔर Teamsसंसाधन स्वचालित रूप से अपडेट हो जाते हैं।


यह वास्तव में TeamsPlayers संसाधन शुरू करने के लिए समझ में आता है। शानदार
vijay

सबसे अच्छा स्पष्टीकरण
डायना

1

मुझे पता है कि इस प्रश्न के लिए स्वीकृत एक उत्तर है, हालांकि, यहां बताया गया है कि हम पहले उठाए गए मुद्दों को कैसे हल कर सकते हैं:

चलो PUT के लिए कहते हैं

PUT    /membership/{collection}/{instance}/{collection}/{instance}/

एक उदाहरण के रूप में, अनुवर्ती सभी को समान प्रभाव की आवश्यकता के बिना सिंक करने की आवश्यकता होगी क्योंकि वे एक ही संसाधन पर किए जाते हैं:

PUT    /membership/teams/team1/players/player1/
PUT    /membership/players/player1/teams/team1/

अब यदि हम एक टीम के लिए कई सदस्यताएँ अद्यतन करना चाहते हैं जो हम इस प्रकार कर सकते हैं (उचित सत्यापन के साथ):

PUT    /membership/teams/team1/

{
    membership: [
        {
            teamId: "team1"
            playerId: "player1"
        },
        {
            teamId: "team1"
            playerId: "player2"
        },
        ...
    ]
}

-3
  1. / खिलाड़ी (एक मास्टर संसाधन है)
  2. / टीमों / {आईडी} / खिलाड़ी (एक संबंध संसाधन है, इसलिए यह अलग-अलग प्रतिक्रिया करता है कि 1)
  3. / सदस्यता (एक संबंध है लेकिन शब्दार्थ रूप से जटिल है)
  4. / खिलाड़ी / सदस्यता (एक संबंध लेकिन शब्दार्थ रूप से जटिल)

मुझे 2 पसंद हैं


2
शायद मैं सिर्फ जवाब नहीं समझता, लेकिन इस पोस्ट में सवाल का जवाब नहीं है।
ब्राडलीडॉटनेट

यह प्रश्न का उत्तर प्रदान नहीं करता है। किसी लेखक से स्पष्टीकरण मांगने या उसका अनुरोध करने के लिए, उनकी पोस्ट के नीचे एक टिप्पणी छोड़ दें - आप हमेशा अपने स्वयं के पोस्ट पर टिप्पणी कर सकते हैं, और एक बार आपके पास पर्याप्त प्रतिष्ठा होने पर आप किसी भी पोस्ट पर टिप्पणी कर पाएंगे ।
अवैध तर्क

4
@IllegalArgument यह है एक जवाब और एक टिप्पणी के रूप में कोई मतलब नहीं होगा। हालांकि, यह सबसे बड़ा जवाब नहीं है।
Qix - मोनासा ने 6

1
इस उत्तर का पालन करना मुश्किल है और कारण प्रदान नहीं करता है।
वेंकट डी।

2
यह पूछे गए प्रश्न का स्पष्टीकरण या उत्तर बिल्कुल नहीं देता है।
मंजीत कुमार
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.