एक जटिल Restful खोज विधि करने का एक उचित तरीका क्या है?


44

REST सिद्धांतों के बाद, मैं अपने API के लिए एक GET विधि बनाना चाहता हूं जो कुछ मानदंडों का उपयोग करके खोज करता है और क्लाइंट को परिणाम लौटाता है। समस्या यह है कि मानदंड में 14 पैरामीटर हो सकते हैं, उनमें से एक जटिल वस्तुओं की एक सूची है, इसलिए ...

  • मुझे यह भी नहीं पता कि इन जटिल वस्तुओं को इनकोड / यूआरएल मापदंडों से इनकोड / डिकोड करना संभव है या नहीं।

  • मैंने गणना नहीं की कि url कब तक मिल सकता है, लेकिन मुझे यकीन है कि यह काफी बड़ा होगा और शायद url की सीमा तक पहुंच सकता है?

इसके अलावा, खोज को "वास्तविक समय" में परिणाम दिखाना चाहिए, मेरा मतलब है कि हर बार जब उपयोगकर्ता खोज फॉर्म से कुछ बदलता है, तो उसे किसी भी "खोज" बटन को दबाए बिना नए परिणाम देखने में सक्षम होना चाहिए।

क्या आप मुझे इन बिंदुओं को स्पष्ट कर सकते हैं और बहुत सारे मापदंडों के साथ एक आरामदायक खोज विधि बनाने के लिए आपकी सलाह क्या होगी?


3
एक तरफ के रूप में (मैं ध्यान देता हूं कि लेखन के समय दोनों में से कोई भी वास्तविक समय भाग का उल्लेख नहीं करता है), वास्तविक समय की खोजों को आम तौर पर केवल अद्यतन अनुरोध को बार-बार भेजना चाहिए। उदाहरण के लिए, जब आप कर रहे हैं टाइपिंग, आप अनुरोध सामान के लिए की तरह भेजने होगी search?q=t, search?q=te, search?q=test, और इतने पर। अपने सर्वर को नुकसान पहुंचाने से बचने के लिए क्वेरी कितनी बार भेजी जाती है, इसे सीमित करने पर विचार करें। तुम भी वैकल्पिक रूप से जानकारी का एक बड़ा सौदा लौट सकते हैं और ग्राहक की ओर से फ़िल्टरिंग करते हैं। यदि उपयोगकर्ता व्यापक श्रेणियों में प्रवेश करता है तो यह अच्छी तरह से काम करता है जो चीजों को बहुत कम कर सकता है।
कैट

2
कोई फर्क नहीं पड़ता समाधान, प्रौद्योगिकी तटस्थ प्रारूप में डेटा का आदान-प्रदान करना सुनिश्चित करें। इसलिए आंतरिक प्रतिनिधित्व का उपयोग न करें या अपने एपीआई के लिए क्लाइंट लिखना कठिन होगा।
कुवेबेल

आपकी आवश्यकताओं के आधार पर, यह लाइब्रेरी काम कर सकती है: github.com/jirutka/rsql-parser । इसका एक JPA एक्सटेंशन है यदि आप JPA का उपयोग करते हैं, या आप अपने खुद के विज़िटर को अपने खोज इंजन की API पर मैप करने के लिए लिख सकते हैं। और आप अपना खुद का ऑपरेटर जोड़ सकते हैं।
वाल्फ्रैट

जवाबों:


54

इससे पहले कि आप मेरा जवाब पढ़ें, मैं कहना चाहूंगा कि मैं @ नील के साथ सहमत था। हमें अपनी लड़ाई चुननी होगी। हम आम तौर पर अपना सर्वश्रेष्ठ प्रदर्शन करना चाहते हैं, लेकिन कभी-कभी चर्चा के लिए बहुत कम जगह होती है और हमें अपनी इच्छा के विरुद्ध निर्णय लेना पड़ता है।

वैसे भी, नील के जवाब में, मुझे एक और बात याद आती है। दस्तावेज़ीकरण । बस यह सुनिश्चित करने के लिए कि डेवलपर्स जानते हैं कि POST अनुरोध /searchसुरक्षित हैं।

ने कहा कि।

1. GET का मौका दें

GETपहले विकल्प पर विचार करें । इस प्रश्न URL की अधिकतम लंबाई देखें । मूल्यांकन करें कि क्या आपकी सबसे लंबी क्वेरी स्ट्रिंग 2000 वर्णों से लंबी है। यदि यह नहीं है, और आप इसे होने की उम्मीद नहीं करते हैं, तो साथ चलें GET। यह बदसूरत लग सकता है, लेकिन कम से कम आप URL को बुकमार्क कर सकते हैं और निश्चित रूप से, यह विधि 'शब्दार्थ (बेदखली, सुरक्षित और कैशिंग) से प्राप्त सभी फायदे हैं।

1.1 क्वेरी स्ट्रिंग एन्कोडिंग का प्रयास करें

उदाहरण के लिए, बेस 64 में। यहां तक ​​कि जावास्क्रिप्ट बेस 64 एनकोडिंग का समर्थन करता है

यह कैसे काम करता है:

  1. सभी फ़िल्टर के साथ JSON बनाएँ और इसे सामान्य करें।
  2. इसे स्ट्रिंग करें
  3. इसे एनकोड करें
  4. अनुरोधित परम ( /search?q=SGVsbG8gV29ybGQh....) के रूप में एन्कोड किए गए JSON भेजें ।
  5. सर्वर-साइड पर, परम q को डिकोड करें ।
  6. JSON स्ट्रिंग का वर्णन करें

पहले, JSON स्ट्रिंग को सबसे लंबे समय तक संभव बनाएं, इसे एनकोड करें और लंबाई लें। मूल्यांकन करें कि क्या एन्कोडेड स्ट्रिंग URL में फिट बैठता है। मैंने आपको परीक्षण करने के लिए Fiddle.js पर निम्नलिखित स्निपेट लागू किया है । (मुझे आशा है कि यह अभी भी काम करता है) 1

बेस 64 एनकोडिंग नियतात्मक और प्रतिवर्ती हैं, इसलिए टक्कर के लिए कोई मौका नहीं है।

एन्कोडेड प्रश्नों के साथ, हम DB में खोजों को भी सहेज सकते हैं, URL को बुकमार्क कर सकते हैं, लिंक साझा कर सकते हैं, आदि। और, निश्चित रूप से, हमें स्ट्रिंग से बचने / अनस्केप करने की आवश्यकता नहीं है।

1.2 उपनाम के साथ प्रयास करें

REST API को डिज़ाइन करने के तरीके के बारे में इस ब्लॉग को पढ़कर , मुझे एक और विकल्प याद आया। सामान्य प्रश्नों के लिए उपनाम

मुझे लगता है कि ये अगले कारणों के लिए दिलचस्प होंगे

  • क्वेरी स्ट्रिंग लंबाई को छोटा करें। यह एपीआई क्लीनर और उपयोगकर्ता के अनुकूल बनाता है

    GET / टिकट / स्टेटस = बंद और बंद किया गया = xxx बनाम GET / टिकट / हाल ही में बंद /

  • अधिक उपनाम या अधिक अनुरोध पैरामीटर के साथ संयोजन।

    GET / टिकट / स्टेटस = बंद और बंद किया गया = xxx और भीतर = 30min बनाम GET / टिकट / हाल ही में बंद / भीतर = 30min?

  • हम उपनामित क्वेरी स्ट्रिंग्स के साथ उपनाम जोड़ सकते हैं

    प्राप्त / टिकट /? स्थिति = बंद कर दिया और closedAt = xxx और भीतर = 30 मिनट बनाम प्राप्त / टिकट / हाल ही में बंद कर दिया /? Q = SGVsbG8g ...


1: मैंने JSON का उपयोग किया है, लेकिन जैसे ही हम सर्वर-साइड पर इसे डीस्सरलाइज़ कर सकते हैं, हम अन्य प्रारूपों का उपयोग कर सकते हैं।


2
यह व्यावहारिक और सही दोनों है। यह भी ध्यान देने योग्य है कि अधिकांश प्रोग्रामिंग भाषाएं एक हैश को एक क्वेरी स्ट्रिंग में बदलने के लिए तुच्छ बनाती हैं, इसलिए एक GET कार्रवाई के साथ शुरू करना बहुत आसान है।
अलुआन हददाद

1
मुझे स्प्रिंग स्टैन्कवरफ़्लो से प्यार है। विजय / 16942193 / ... मुझे विश्वास नहीं हो रहा है कि यह पहली कोशिश में काम किया: डी। यूआरएल लेन के बारे में, 1k से कम है, हालांकि हमें अभी भी चश्मा को पुनरावृत्त करने की आवश्यकता है।
anat0lius

फिर, GET के साथ जाएं। सरलता के लिए। स्प्रिंग एमवीसी के साथ, आप जीईटी के साथ बहुत ही मानचित्रण प्राप्त कर सकते हैं। वसंत के WebArgumentResolver के लिए ;-) देखो
Laiv

Base64 लगभग 4/3 द्वारा पेलोड का आकार बढ़ाता है। जबकि urlencoding विशेष वर्णों के लिए इसे 3/1 कर सकती है, अधिकतर सुरक्षित वर्णों के साथ प्रश्न समान आकार रखने वाले हैं। क्या बेस 64 का उपयोग करने का कोई अन्य कारण है?
विलास

ज़रुरी नहीं। मैं केवल URL को नापसंद (अन) करता हूं। पेलोड की अधिकता यहाँ व्यापार है। यह अभी भी GET के अधिकतम आकार के अनुरोध के अनुसार फिट होना है। इसलिए मैंने स्निपेट बनाया। उपयोगकर्ता के लिए प्रयास करने के लिए। जब मैंने उत्तर लिखा, तो मैंने कार्यान्वयन विवरण पर वेब शब्दार्थों को प्राथमिकता दी। उत्तर का पूरा बिंदु "GET के साथ प्रयास करते रहना" है। अपना रास्ता खोजें या इनमें से किसी एक का उपयोग करें जिसे मैं आपके साथ साझा करता हूं।
लैवि

13

यदि आपके पास एक हथौड़ा है, तो सब कुछ एक नाखून की तरह दिखता है। ऐसा लगता है कि समस्या यह है कि आप खोज पृष्ठ को Restful में बदलने की कोशिश कर रहे हैं, और यह शायद ही कभी Restful डिजाइन को हल करने के लिए एक सामान्य पैटर्न लगता है।

बैकएंड से आवश्यक जानकारी प्राप्त करने के लिए उपयोगकर्ता द्वारा प्रदान किए गए मापदंडों के साथ बस एक POST अनुरोध के साथ जाएं। मुझे लगता है कि आपको खोज करने के अलावा कुछ करने की आवश्यकता नहीं है, इसलिए इस पृष्ठ के माध्यम से आपको सम्मिलित करने की आवश्यकता नहीं होगी। बस अपने URL के अंत में एक / खोज जोड़ें ताकि आप अपने / उपयोगकर्ताओं पृष्ठ के साथ संघर्ष में भाग लेने का जोखिम न लें जो कि RESTful होगा


2
@LiLou_: उस आवश्यकता के लिए, केवल दो यथार्थवादी संभावनाएं हैं: 1. अपने सामने के अंत के सभी डेटा पढ़ें और वहां फ़िल्टर करें। यह आवश्यक मात्रा में स्मृति में निषेधात्मक हो सकता है। 2. खोज मापदंड में प्रत्येक परिवर्तन के लिए सर्वर से एक नया अनुरोध करें। इससे कोई फर्क नहीं पड़ता कि यह एक POST या GET अनुरोध है, लेकिन इसमें शामिल नेटवर्क विलंबता "वास्तविक समय" अपडेट के उपयोगकर्ता की भावना के लिए विघटनकारी हो सकती है।
बार्ट वैन इनगेन शेनॉ

2
मैं असहमत होने के लिए सहमत हूं, POST का अर्थ कुछ और है। मैं GET के साथ जाने और क्वेरी पैरामीटर में सभी फ़िल्टर डेटा को अब पास करने का सुझाव दूंगा यदि बहुत अधिक पैरामीटर हैं तो यह अनुप्रयोग स्तर पर एक गलती है।
कोडयोगी

2
@CodeYogi कभी-कभी ग्राहक आपको भ्रम के लिए जगह नहीं देता है। मैंने 40-50 कॉलम वाले एक्सेल जैसे व्यू पेजों को लागू किया है, जिनमें से प्रत्येक अपने स्वयं के फ़िल्टर के साथ है। और क्रमबद्ध। वैसे भी, GET के साथ अभी भी संभव है लेकिन यह बहुत फैशन नहीं लग सकता है
Laiv

1
@ उस मामले में गंभीर चर्चा होने की आवश्यकता है क्योंकि POST सर्वर स्थिति में परिवर्तन के लिए है। इस तरह के उपयोग के मामले असाधारण नहीं हैं इसलिए बिना हैक्स का ध्यान रखा जाना चाहिए।
कोडयोगी

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

0

यह पूरी तरह से इस बात पर निर्भर करता है कि आपका API मॉडल क्या है: कोई नहीं या क्रिया के रूप में।

यदि एपीआई कोई नहीं है तो आप निम्नलिखित के रूप में वस्तुओं की सूची प्राप्त करना चाहते हैं:

GET: /api/v1/objects

इस मामले में आपको अनुरोध पैरामीटर के रूप में डेटा भेजना होगा। इसलिए आपको अपने मापदंडों को कुंजी-मानों की एक फ्लैट सूची के रूप में वर्णित करना होगा:

GET: /api/v1/objects

key1 : val1
key2.key1 : val 21
key2.key2 : val 22
....

कुछ प्लेटफ़ॉर्म कस्टम पैरामीटर रिज़ॉल्वर (जैसे स्प्रिंग एमवीसी) का समर्थन करते हैं, आप एक परमिशन को ऑब्जेक्ट में बदल सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.