एपीआई पेजिनेशन सर्वोत्तम प्रथाओं


288

मुझे लगता है कि मैं निर्माण कर रहा हूँ एक पागल एपीआई के साथ एक अजीब धार मामले को संभालने में कुछ मदद पसंद करेंगे।

कई एपीआई की तरह, यह एक बड़ा परिणाम देता है। यदि आप क्वेरी करते / करते हैं, तो आपको 100 परिणाम (अर्थात # # 1-100), और / foos के लिए एक लिंक मिलेगा? पेज = 2 जो फू # 101-200 को वापस करना चाहिए।

दुर्भाग्य से, अगर एपीआई उपभोक्ता के अगली क्वेरी बनाने से पहले डेटा सेट से foo # 10 को हटा दिया जाता है, तो पृष्ठ / 2? पेज = 2 100 से ऑफसेट होगा और फॉल्स # 102-201 पर वापस आ जाएगा।

यह एपीआई उपभोक्ताओं के लिए एक समस्या है, जो सभी फॉक्स को खींचने की कोशिश कर रहे हैं - वे फू # 101 प्राप्त नहीं करेंगे।

इसे संभालने के लिए सबसे अच्छा अभ्यास क्या है? हम इसे जितना संभव हो उतना हल्का बनाना चाहते हैं (यानी एपीआई अनुरोधों के लिए सत्र से बचने के लिए)। अन्य एपीआई के उदाहरणों की बहुत सराहना की जाएगी!


1
यहाँ क्या समस्या है? मेरे लिए ठीक है, किसी भी तरह से उपयोगकर्ता को 100 आइटम मिलेंगे।
NARKOZ

2
मैं इसी मुद्दे का सामना कर रहा हूं और इसका हल ढूंढ रहा हूं। AFAIK, इसे पूरा करने के लिए वास्तव में कोई ठोस गारंटी तंत्र नहीं है, यदि प्रत्येक पृष्ठ एक नई क्वेरी निष्पादित करता है। एकमात्र समाधान जिसके बारे में मैं सोच सकता हूं, एक सक्रिय सत्र रखना है, और परिणाम को सर्वर साइड में रखना है, और प्रत्येक पृष्ठ के लिए नए प्रश्नों को निष्पादित करने के बजाय, बस रिकॉर्ड के अगले कैश्ड सेट को पकड़ो।
जेरी डॉज

31
एक नज़र डालें कि ट्विटर इस dev.twitter.com/rest/public/timelines
java_geek

1
@java_geek how_id पैरामीटर कैसे अपडेट किया गया है? ट्विटर के वेबपेज में ऐसा लगता है जैसे वे दोनों अनुरोधों को एक ही मान के साथ बना रहे हैं। मुझे आश्चर्य है कि इसे कब अपडेट किया जाएगा ताकि अगर नए ट्वीट्स जोड़े जाएं, तो उनका हिसाब लगाया जा सके?
पेटर

1
@Petar के बाद से API के उपभोक्ता द्वारा अद्यतन किया जाना चाहिए। यदि आप देखते हैं, तो वहाँ उदाहरण ट्वीट प्रसंस्करण करने वाले ग्राहकों को संदर्भित करता है
java_geek

जवाबों:


176

मुझे पूरी तरह से यकीन नहीं है कि आपका डेटा कैसे संभाला जाता है, इसलिए यह काम कर भी सकता है और नहीं भी, लेकिन क्या आपने टाइमस्टैम्प फील्ड के साथ पेजिंग करने पर विचार किया है?

जब आप क्वेरी / फ़ॉउस करते हैं तो आपको 100 परिणाम मिलते हैं। आपके API को कुछ इस तरह से लौटना चाहिए (JSON मानकर, लेकिन अगर इसे XML की आवश्यकता हो तो उसी सिद्धांतों का पालन किया जा सकता है):

{
    "data" : [
        {  data item 1 with all relevant fields    },
        {  data item 2   },
        ...
        {  data item 100 }
    ],
    "paging":  {
        "previous":  "http://api.example.com/foo?since=TIMESTAMP1" 
        "next":  "http://api.example.com/foo?since=TIMESTAMP2"
    }

}

केवल एक नोट, केवल एक टाइमस्टैम्प का उपयोग करना आपके परिणामों में एक अंतर्निहित 'सीमा' पर निर्भर करता है। आप एक स्पष्ट सीमा जोड़ना चाहते हैं या एक untilसंपत्ति का उपयोग भी कर सकते हैं।

सूची में अंतिम डेटा आइटम का उपयोग करके टाइमस्टैम्प को गतिशील रूप से निर्धारित किया जा सकता है। यह कमोबेश ऐसा लगता है कि कैसे फेसबुक अपने ग्राफ़ एपीआई (नीचे दिए गए प्रारूप में पृष्ठांकन लिंक देखने के लिए नीचे स्क्रॉल करें)।

यदि आप एक डेटा आइटम जोड़ते हैं, तो एक समस्या हो सकती है, लेकिन आपके विवरण के आधार पर ऐसा लगता है कि वे अंत में जोड़े जाएंगे (यदि नहीं, तो मुझे बताएं और मैं देखूंगा कि क्या मैं इस पर सुधार कर सकता हूं)।


30
टाइमस्टैम्प अद्वितीय होने की गारंटी नहीं है। यही है, एक ही टाइमस्टैम्प के साथ कई संसाधन बनाए जा सकते हैं। इसलिए इस दृष्टिकोण में नकारात्मक पक्ष यह है कि अगला पृष्ठ, वर्तमान पृष्ठ से अंतिम (कुछ?) प्रविष्टियों को दोहरा सकता है।
रूबल

4
@prmatta वास्तव में, डेटाबेस कार्यान्वयन के आधार पर एक टाइमस्टैम्प अद्वितीय होने की गारंटी है
रंबलिनजन

2
@jandjorgensen आपके लिंक से: "टाइमस्टैम्प डेटा प्रकार केवल एक वृद्धि की संख्या है और यह किसी दिनांक या समय को संरक्षित नहीं करता है ... SQL Server 2008 और बाद में, टाइमस्टैम्प प्रकार को पंक्तिबद्ध करने के लिए नाम दिया गया है , संभवतः बेहतर प्रतिबिंबित करने के लिए। उद्देश्य और मूल्य। " इसलिए यहाँ कोई सबूत नहीं है कि टाइमस्टैम्प (जो वास्तव में एक समय मान रखते हैं) अद्वितीय हैं।
नोलन एमी

3
@jandjorgensen मुझे आपका प्रस्ताव पसंद है, लेकिन क्या आपको संसाधन लिंक में किसी प्रकार की जानकारी की आवश्यकता नहीं होगी, इसलिए हमें पता है कि क्या हम पिछले या अगले पर जाते हैं? जैसे: "पिछला": " api.example.com/foo?before=TIMESTAMP " "अगला": " api.example.com/foo?since=TIMESTAMP2 " हम भी टाइमस्टैम्प के बजाय अपने अनुक्रम आईडी का उपयोग करेंगे। क्या आप इसके साथ कोई समस्या देखते हैं?
लॉन्गलीवेन्डुरो

5
इसी तरह का एक अन्य विकल्प RFC 5988 (धारा 5) में निर्दिष्ट लिंक हेडर क्षेत्र का उपयोग करना है: tools.ietf.org/html/rfc5988#page-6
एंथनी एफ

28

आपको कई समस्याएं हैं।

सबसे पहले, आपके पास उदाहरण है जिसे आपने उद्धृत किया है।

यदि आपको पंक्तियाँ डाली जाती हैं, तो आपको एक समान समस्या है, लेकिन इस मामले में उपयोगकर्ता को डुप्लिकेट डेटा मिलता है (लापता डेटा की तुलना में प्रबंधित करना आसान है, लेकिन अभी भी एक समस्या है)।

यदि आप मूल डेटा सेट को स्नैपशॉट नहीं कर रहे हैं, तो यह जीवन का एक तथ्य है।

आप उपयोगकर्ता को एक स्पष्ट स्नैपशॉट बना सकते हैं:

POST /createquery
filter.firstName=Bob&filter.lastName=Eubanks

जो परिणाम:

HTTP/1.1 301 Here's your query
Location: http://www.example.org/query/12345

फिर आप इसे दिन भर का पेज बना सकते हैं, क्योंकि यह अब स्थिर है। यह काफी हल्का वजन हो सकता है, क्योंकि आप पूरी पंक्तियों के बजाय वास्तविक दस्तावेज़ कुंजियों को पकड़ सकते हैं।

यदि उपयोग का मामला केवल यह है कि आपके उपयोगकर्ता (और आवश्यकता) सभी डेटा चाहते हैं, तो आप बस उन्हें दे सकते हैं:

GET /query/12345?all=true

और बस पूरी किट भेजें।


1
(फॉक्स का डिफ़ॉल्ट प्रकार निर्माण की तारीख से है, इसलिए पंक्ति सम्मिलन कोई समस्या नहीं है।)
2arrs2ells

दरअसल, केवल दस्तावेज़ कुंजियों पर कब्जा करना पर्याप्त नहीं है। इस तरह से आपको आईडी द्वारा पूर्ण वस्तुओं को क्वेरी करना होगा जब उपयोगकर्ता उनसे अनुरोध करता है, लेकिन यह हो सकता है कि वे अब मौजूद नहीं हैं।
स्केज करें

27

यदि आपको पृष्ठांकन मिला है तो आप कुछ कुंजी द्वारा डेटा को सॉर्ट भी करते हैं। एपीआई क्लाइंट को URL में पहले दिए गए संग्रह के अंतिम तत्व की कुंजी क्यों शामिल नहीं करने दें और WHEREअपनी SQL क्वेरी (या कुछ समतुल्य, यदि आप SQL का उपयोग नहीं कर रहे हैं) के लिए एक खंड जोड़ें , ताकि यह केवल उन तत्वों को लौटाए जिसके लिए कुंजी इस मूल्य से अधिक है?


4
यह एक बुरा सुझाव नहीं है, हालांकि सिर्फ इसलिए कि आप एक मूल्य के आधार पर क्रमबद्ध करते हैं इसका मतलब यह नहीं है कि यह एक 'कुंजी' है, अर्थात अद्वितीय।
क्रिस पीकॉक

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

19

आपके सर्वर साइड लॉजिक के आधार पर दो दृष्टिकोण हो सकते हैं।

दृष्टिकोण 1: जब सर्वर ऑब्जेक्ट स्टेट्स को संभालने के लिए पर्याप्त स्मार्ट नहीं है।

आप सभी कैश्ड रिकॉर्ड यूनिक आईडी सर्वर पर भेज सकते हैं, उदाहरण के लिए ["id1", "id2", "id3", "id4", "id5", "id6", "id7", "id8", "id9", "id10"] और एक बूलियन पैरामीटर यह जानने के लिए कि क्या आप नए रिकॉर्ड (ताज़ा करने के लिए पुल) या पुराने रिकॉर्ड (लोड अधिक) का अनुरोध कर रहे हैं।

आपके गंभीर को नए रिकॉर्ड वापस करने के लिए जिम्मेदार होना चाहिए (ताज़ा करने के लिए पुल के माध्यम से अधिक रिकॉर्ड या नए रिकॉर्ड लोड करें) और साथ ही आईडी के हटाए गए रिकॉर्ड से "" आईडी 1 "," आईडी 2 "," आईडी 3 "," आईडी 4 "," आईडी 5 "," id6 "," id7 "," id8 "," id9 "," ID10 "]।

उदाहरण: - यदि आप अधिक लोड का अनुरोध कर रहे हैं तो आपके अनुरोध को कुछ इस तरह दिखना चाहिए: -

{
        "isRefresh" : false,
        "cached" : ["id1","id2","id3","id4","id5","id6","id7","id8","id9","id10"]
}

अब मान लें कि आप पुराने रिकॉर्ड (लोड अधिक) का अनुरोध कर रहे हैं और मान लें कि "id2" रिकॉर्ड किसी व्यक्ति द्वारा अपडेट किया गया है और "id5" और "id8" रिकॉर्ड सर्वर से हटा दिया गया है, तो आपके सर्वर की प्रतिक्रिया कुछ इस तरह दिखनी चाहिए: -

{
        "records" : [
{"id" :"id2","more_key":"updated_value"},
{"id" :"id11","more_key":"more_value"},
{"id" :"id12","more_key":"more_value"},
{"id" :"id13","more_key":"more_value"},
{"id" :"id14","more_key":"more_value"},
{"id" :"id15","more_key":"more_value"},
{"id" :"id16","more_key":"more_value"},
{"id" :"id17","more_key":"more_value"},
{"id" :"id18","more_key":"more_value"},
{"id" :"id19","more_key":"more_value"},
{"id" :"id20","more_key":"more_value"}],
        "deleted" : ["id5","id8"]
}

लेकिन इस मामले में अगर आपने बहुत सारे स्थानीय कैश किए गए रिकॉर्ड 500 मान लिए हैं, तो आपका अनुरोध स्ट्रिंग इस तरह बहुत लंबा हो जाएगा: -

{
        "isRefresh" : false,
        "cached" : ["id1","id2","id3","id4","id5","id6","id7","id8","id9","id10",………,"id500"]//Too long request
}

दृष्टिकोण 2: जब दिनांक के अनुसार ऑब्जेक्ट राज्यों को संभालने के लिए सर्वर काफी स्मार्ट होता है।

आप पहले रिकॉर्ड और अंतिम रिकॉर्ड और पिछले अनुरोध के समय की आईडी भेज सकते हैं। इस तरह से आपका अनुरोध हमेशा छोटा होता है, भले ही आपके पास कैश्ड रिकॉर्ड की एक बड़ी मात्रा हो

उदाहरण: - यदि आप अधिक लोड का अनुरोध कर रहे हैं तो आपके अनुरोध को कुछ इस तरह दिखना चाहिए: -

{
        "isRefresh" : false,
        "firstId" : "id1",
        "lastId" : "id10",
        "last_request_time" : 1421748005
}

आपका सर्वर हटाए गए रिकॉर्ड्स की आईडी को वापस करने के लिए ज़िम्मेदार है, जिसे last_request_time के बाद हटा दिया गया है और साथ ही "id1" और "id10" के बीच last_request_time के बाद अपडेट किया गया रिकॉर्ड लौटाएं।

{
        "records" : [
{"id" :"id2","more_key":"updated_value"},
{"id" :"id11","more_key":"more_value"},
{"id" :"id12","more_key":"more_value"},
{"id" :"id13","more_key":"more_value"},
{"id" :"id14","more_key":"more_value"},
{"id" :"id15","more_key":"more_value"},
{"id" :"id16","more_key":"more_value"},
{"id" :"id17","more_key":"more_value"},
{"id" :"id18","more_key":"more_value"},
{"id" :"id19","more_key":"more_value"},
{"id" :"id20","more_key":"more_value"}],
        "deleted" : ["id5","id8"]
}

रीफ़्रेश करने के लिए खींचें:-

यहां छवि विवरण दर्ज करें

और लोड करें

यहां छवि विवरण दर्ज करें


14

यह सबसे अच्छा अभ्यास खोजने के लिए कठिन हो सकता है क्योंकि एपीआई वाले अधिकांश सिस्टम इस परिदृश्य के लिए समायोजित नहीं करते हैं, क्योंकि यह एक चरम बढ़त है, या वे आम तौर पर रिकॉर्ड (फेसबुक, ट्विटर) को नष्ट नहीं करते हैं। फेसबुक वास्तव में कहता है कि प्रत्येक "पृष्ठ" में पृष्ठांकन के बाद किए गए फ़िल्टरिंग के कारण अपेक्षित परिणाम नहीं हो सकते हैं। https://developers.facebook.com/blog/post/478/

यदि आपको वास्तव में इस किनारे के मामले को समायोजित करने की आवश्यकता है, तो आपको "याद रखना" चाहिए जहां आपने छोड़ा था। jandjorgensen सुझाव अभी मौके पर है, लेकिन मैं प्राथमिक कुंजी की तरह अद्वितीय होने की गारंटी वाले क्षेत्र का उपयोग करूंगा। आपको एक से अधिक फ़ील्ड का उपयोग करने की आवश्यकता हो सकती है।

फेसबुक के प्रवाह के बाद, आप पहले से अनुरोध किए गए पृष्ठों को कैश (और कर सकते हैं) और यदि वे पहले से ही अनुरोध किए गए पृष्ठ का अनुरोध करते हैं, तो उन्हें हटाए गए पंक्तियों के साथ वापस लौटाएं।


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

3
मैं असहमत हूं। सिर्फ यूनिक आईडी रखने से ज्यादा मेमोरी का इस्तेमाल नहीं होता है। आप केवल "सत्र" के लिए डेटा को अनिश्चित काल तक बनाए रखने की आवश्यकता नहीं है। यह मेमेचे के साथ आसान है, बस समाप्ति अवधि (यानी 10 मिनट) निर्धारित करें।
ब्रेंट बैस्ले

मेमोरी नेटवर्क / सीपीयू स्पीड से सस्ती है। इसलिए यदि एक पेज बनाना बहुत महंगा है (नेटवर्क के संदर्भ में या सीपीयू गहन है), तो कैशिंग परिणाम एक वैध दृष्टिकोण है @DeepakGarg
U Avalos

9

पृष्ठांकन आम तौर पर एक "उपयोगकर्ता" ऑपरेशन है और कंप्यूटर और मानव मस्तिष्क दोनों पर अधिभार को रोकने के लिए आप आमतौर पर एक सबसेट देते हैं। हालांकि, यह सोचने के बजाय कि हमें पूरी सूची नहीं मिलती है यह पूछना बेहतर होगा कि क्या यह मायने रखता है?

यदि एक सटीक लाइव स्क्रॉलिंग दृश्य की आवश्यकता है, तो REST API जो प्रकृति में अनुरोध / प्रतिक्रिया है, इस उद्देश्य के लिए अच्छी तरह से अनुकूल नहीं हैं। इसके लिए आपको बदलावों से निपटने के दौरान अपने फ्रंट एंड को जानने के लिए वेबस्केट्स या एचटीएमएल 5 सर्वर-सेंटेड इवेंट्स पर विचार करना चाहिए।

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

मेरे मामले के लिए मैंने पूरी जानकारी (मुख्य रूप से संदर्भ तालिका डेटा) प्राप्त करने की अनुमति देने के लिए कुछ एपीआई कॉलों का अनुमान लगाया है। आप इन API को सुरक्षित भी कर सकते हैं ताकि यह आपके सिस्टम को नुकसान न पहुंचाए।


8

विकल्प A: टाइमस्टैम्प के साथ कीगेट पेजिनेशन

आपके द्वारा उल्लिखित ऑफसेट पृष्ठांकन की कमियों से बचने के लिए, आप कीसेट आधारित पेजिनेशन का उपयोग कर सकते हैं। आमतौर पर, संस्थाओं के पास एक टाइमस्टैम्प होता है जो उनके निर्माण या संशोधन के समय को बताता है। इस टाइमस्टैम्प का उपयोग पृष्ठांकन के लिए किया जा सकता है: बस अंतिम तत्व के टाइमस्टैम्प को अगले अनुरोध के लिए क्वेरी पैरामीटर के रूप में पास करें। सर्वर, बदले में, टाइमस्टैम्प को एक फिल्टर मानदंड (जैसे WHERE modificationDate >= receivedTimestampParameter) के रूप में उपयोग करता है

{
    "elements": [
        {"data": "data", "modificationDate": 1512757070}
        {"data": "data", "modificationDate": 1512757071}
        {"data": "data", "modificationDate": 1512757072}
    ],
    "pagination": {
        "lastModificationDate": 1512757072,
        "nextPage": "https://domain.de/api/elements?modifiedSince=1512757072"
    }
}

इस तरह, आप किसी भी तत्व को याद नहीं करेंगे। यह दृष्टिकोण कई उपयोग मामलों के लिए पर्याप्त होना चाहिए। हालांकि, निम्नलिखित को ध्यान में रखें:

  • जब आप किसी एकल पृष्ठ के सभी तत्वों का समान टाइमस्टैम्प है, तो आप अंतहीन लूप में चल सकते हैं।
  • जब ग्राहक एक ही टाइमस्टैम्प के साथ दो पेजों को ओवरलैप कर रहे हों तो आप कई बार क्लाइंट को कई बार डिलीवर कर सकते हैं।

आप पृष्ठ का आकार बढ़ाकर और मिलीसेकंड परिशुद्धता के साथ टाइमस्टैम्प का उपयोग करके उन कमियों की संभावना कम कर सकते हैं।

विकल्प बी: कंटीन्यूएशन टोकन के साथ विस्तारित कीगेट पेजिनेशन

सामान्य कीसेट पेजिंग के उल्लिखित कमियों को संभालने के लिए, आप टाइमस्टैम्प में एक ऑफसेट जोड़ सकते हैं और एक तथाकथित "कॉन्टीन्यूशन टोकन" या "कर्सर" का उपयोग कर सकते हैं। ऑफसेट एक ही टाइमस्टैम्प के साथ पहले तत्व के सापेक्ष तत्व की स्थिति है। आमतौर पर, टोकन में एक प्रारूप होता है जैसे Timestamp_Offset। यह क्लाइंट को प्रतिक्रिया में दिया गया है और अगले पेज को पुनः प्राप्त करने के लिए सर्वर में वापस जमा किया जा सकता है।

{
    "elements": [
        {"data": "data", "modificationDate": 1512757070}
        {"data": "data", "modificationDate": 1512757072}
        {"data": "data", "modificationDate": 1512757072}
    ],
    "pagination": {
        "continuationToken": "1512757072_2",
        "nextPage": "https://domain.de/api/elements?continuationToken=1512757072_2"
    }
}

टोकन "1512757072_2" पृष्ठ के अंतिम तत्व को इंगित करता है और कहता है "ग्राहक को पहले से ही टाइमस्टैम्प 1512757072 के साथ दूसरा तत्व मिला है"। इस तरह, सर्वर जानता है कि कहां जारी रखना है।

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

इस दृष्टिकोण के बारे में अधिक जानकारी के लिए ब्लॉग पोस्ट " कंटीन्यू विथ कंटीन्यूएशन वेब वेब पेजिंग " देखें। इस दृष्टिकोण का एक दोषपूर्ण कार्यान्वयन है क्योंकि कई कोने मामले हैं जिन्हें ध्यान में रखा जाना है। यही कारण है कि निरंतरता-टोकन जैसे पुस्तकालय काम कर सकते हैं (यदि आप जावा / एक जेवीएम भाषा का उपयोग कर रहे हैं)। डिस्क्लेमर: मैं पोस्ट का लेखक और लाइब्रेरी का सह-लेखक हूं।


4

मुझे लगता है कि वर्तमान में आपकी एपीआई वास्तव में उस तरह से जवाब दे रही है जैसे उसे करना चाहिए। आपके द्वारा बनाए जा रहे ऑब्जेक्ट्स के समग्र क्रम में पृष्ठ पर पहले 100 रिकॉर्ड। आपकी व्याख्या बताती है कि आप पृष्ठांकन के लिए अपनी वस्तुओं के क्रम को परिभाषित करने के लिए किसी प्रकार के ऑर्डरिंग आईडी का उपयोग कर रहे हैं।

अब, यदि आप चाहते हैं कि पेज 2 हमेशा 101 से शुरू होना चाहिए और 200 पर समाप्त होना चाहिए, तो आपको पृष्ठ पर प्रविष्टियों की संख्या को चर के रूप में बनाना चाहिए, क्योंकि वे विलोपन के अधीन हैं।

आपको नीचे दिए गए स्यूडोकोड की तरह कुछ करना चाहिए:

page_max = 100
def get_page_results(page_no) :

    start = (page_no - 1) * page_max + 1
    end = page_no * page_max

    return fetch_results_by_id_between(start, end)

1
मैं सहमत हूँ। रिकॉर्ड संख्या द्वारा क्वेरी के बजाय (जो विश्वसनीय नहीं है) आपको आईडी द्वारा क्वेरी करनी चाहिए। अपनी क्वेरी (x, m) को "आईडी द्वारा दर्ज किए गए m रिकॉर्ड पर लौटें, ID> x" के साथ बदलें, फिर आप बस पिछले क्वेरी परिणाम से अधिकतम आईडी पर x सेट कर सकते हैं।
जॉन हेनकेल

यह सच है, या तो आईडी पर सॉर्ट करें या यदि आपके पास कुछ ठोस व्यवसाय क्षेत्र है जैसे
क्रिएशन_डेट

4

सिर्फ कामिलक द्वारा इस उत्तर को जोड़ने के लिए: https://www.stackoverflow.com/a/13905589

निर्भर करता है कि आप कितने बड़े डेटासेट पर काम कर रहे हैं। छोटे डेटा सेट ऑफ़सेट पेजिनेशन पर प्रभावी ढंग से काम करते हैं लेकिन बड़े रियलटाइम डेटासेट की आवश्यकता होती है कर्सर पेजेशन की है।

एक अद्भुत लेख मिला कि कैसे स्लैक ने अपने एपि के पेजिनेशन को विकसित किया क्योंकि डेटासेट हर चरण में सकारात्मकता और नकारात्मकता को बढ़ाता है: https://slack.engineering/evolve-ap-pagination-at-slack.c1f644f8e12


3

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

किसी आइटम को हटाए जाने का आपका उदाहरण केवल हिमशैल का टिप है। क्या होगा यदि आप फ़िल्टर कर रहे हैं, color=blueलेकिन कोई अनुरोधों के बीच आइटम रंग बदलता है? सभी वस्तुओं को चरणबद्ध तरीके से प्राप्त करना असंभव है ... जब तक ... हम संशोधन इतिहास को लागू नहीं करते हैं

मैंने इसे लागू किया है और यह वास्तव में मेरी अपेक्षा से कम कठिन है। यहाँ मैंने क्या किया है:

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

मैं उलझन में हूं। यह आपके द्वारा उल्लिखित उपयोग के मामले को कैसे हल करेगा? (कैश में एक यादृच्छिक क्षेत्र बदलता है और आप कैश को अमान्य करना चाहते हैं)
यू एवलोस

आपके द्वारा किए गए किसी भी परिवर्तन के लिए, आप केवल प्रतिक्रिया को देखते हैं। सर्वर एक नया परिवर्तन प्रदान करेगा और आप अपने अगले अनुरोध में इसका उपयोग करते हैं। अन्य परिवर्तनों के लिए (अन्य लोगों द्वारा किए गए), आप या तो नवीनतम परिवर्तन को हर बार एक बार में प्रदूषित करते हैं और यदि यह आपके स्वयं के मुकाबले अधिक है, तो आप जानते हैं कि बकाया परिवर्तन हैं। या आप कुछ नोटिफिकेशन सिस्टम (लॉन्ग पोलिंग। सर्वर पुश, वेबसोकेट्स) सेट करते हैं जो क्लाइंट को अलर्ट करता है जब उसमें कोई बदलाव होता है।
स्टिजन डे विट

0

RESTFul API में पेजिनेशन का एक अन्य विकल्प, यहाँ प्रस्तुत लिंक हेडर का उपयोग करना है । उदाहरण के लिए गितुब इसे निम्नानुसार उपयोग करते हैं:

Link: <https://api.github.com/user/repos?page=3&per_page=100>; rel="next",
  <https://api.github.com/user/repos?page=50&per_page=100>; rel="last"

इसके लिए संभावित मान relहैं: पहला, अंतिम, अगला, पिछला । लेकिन Linkशीर्ष लेख का उपयोग करके , यह संभव नहीं हो सकता है कि कुल_काउंट (तत्वों की कुल संख्या) निर्दिष्ट करें ।

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