موبائل ڈیولپمنٹ میں Cursor Pagination — یہ کیا ہے، اصول اور نفاذ

مصنف: IT Sectr اشاعت: 2026-03-11 مطالعے کا وقت: 9 منٹ

Cursor Pagination ڈیٹا لوڈ کرنے کا ایک صفحہ وار طریقہ ہے جو ریکارڈز کے ترتیب شدہ سیٹ میں نیویگیشن کے لیے ایک منفرد کرسر استعمال کرتا ہے۔ GraphQL Specification (2025) کے مطابق، کرسر پر مبنی صفحہ بندی متحرک ڈیٹا کے ساتھ کام کرنے والے APIs کے لیے تجویز کردہ معیار ہے۔ Cursor pagination Offset طریقہ کار کی اہم خامیوں کو ختم کرتا ہے: اندراج کے دوران عدم استحکام اور بڑی آفسیٹس پر کارکردگی کا بگاڑ۔

اہم نکات

  • Cursor Pagination ایک صفحہ بندی کا طریقہ ہے جہاں ہر ریکارڈ میں نیویگیشن کے لیے ایک منفرد کرسر شناخت کنندہ ہوتا ہے۔
  • کرسر ڈیٹا سیٹ میں ایک منفرد مقام کا نشان ہے (عام طور پر ID، UUID، timestamp) جو اندراج پر تبدیل نہیں ہوتا۔
  • استحکام — درخواستوں کے درمیان شامل کردہ نئے ریکارڈ کرسر کو منتقل نہیں کرتے، نقل اور خلا کو ختم کرتے ہیں۔
  • کارکردگی — WHERE id > cursor استفسار بڑے ڈیٹاسیٹس پر رفتار کھوئے بغیر انڈیکس کو مؤثر طریقے سے استعمال کرتا ہے۔
  • حدود — کرسر صفحہ بندی صفحہ نمبر کے ذریعے نیویگیشن کی حمایت نہیں کرتی (آپ صفحہ 5 پر نہیں جا سکتے)۔

Cursor Pagination کیا ہے؟

Cursor Pagination ایک صفحہ وار لوڈنگ کا طریقہ ہے جہاں سرور ڈیٹا کے ساتھ ایک خاص پوائنٹر — کرسر — واپس کرتا ہے۔ کلائنٹ ریکارڈز کا اگلا بیچ حاصل کرنے کے لیے اگلی درخواست میں اس کرسر کا استعمال کرتا ہے۔ کرسر موجودہ صفحہ کے آخری عنصر کی منفرد شناخت ہے۔

Offset صفحہ بندی کے برعکس، جہاں کلائنٹ کہتا ہے “مجھے 20 ریکارڈز کے ساتھ صفحہ 5 دیں،” کرسر صفحہ بندی مختلف طریقے سے کام کرتی ہے: “مجھے ID = 83 والے ریکارڈ کے بعد 20 ریکارڈ دیں۔” سرور WHERE id > 83 اور LIMIT 20 کے ساتھ استفسار چلاتا ہے۔ یہ طریقہ اس بات کی ضمانت دیتا ہے کہ ہر ریکارڈ اندراج سے قطع نظر بالکل ایک صفحہ میں آتا ہے۔

کرسر صفحہ بندی کے تصور کو Relay Connection (GraphQL) تصریح کی بدولت وسیع پیمانے پر اپنایا گیا، جس نے کرسر پر مبنی صفحہ بندی کو جدید APIs کے لیے معیار بنا دیا۔ Relay جوابی فارمیٹ کی وضاحت کرتا ہے: edges (کرسرز کے ساتھ ریکارڈز کی صف)، pageInfo (hasNextPage، hasPreviousPage، startCursor، endCursor)۔

تاریخ

کرسر صفحہ بندی کوئی نئی تکنیک نہیں ہے — یہ ویب سے بہت پہلے ڈیٹابیسز میں استعمال ہوتی تھی۔ SQL میں اسے keyset pagination یا seek method کہا جاتا ہے۔ یہ طریقہ 2015 میں Relay تصریح کی اشاعت کے بعد APIs میں مقبول ہوا، جس نے HTTP ٹرانسپورٹ پر یکسانیت کے لیے کرسر فارمیٹ کو base64-انکوڈڈ سٹرنگ کے طور پر رسمی شکل دی۔

کرسر صفحہ بندی کیسے کام کرتی ہے

کرسر صفحہ بندی کا بنیادی اصول یہ ہے کہ استفسار مقام تعین کرنے کے لیے آفسیٹ کی بجائے انڈیکسڈ فیلڈ پر WHERE شرط استعمال کرتا ہے۔ آگے کی سمت کے لیے WHERE id > last_id استعمال ہوتا ہے؛ پیچھے کی سمت کے لیے WHERE id < first_id۔ B-tree انڈیکس کرسر کے بعد پہلا ریکارڈ O(log n) میں ڈھونڈتا ہے، جو مستحکم جوابی وقت فراہم کرتا ہے۔

sql
-- کرسر '83' کے بعد 20 ریکارڈ حاصل کریں
SELECT id, title, created_at
FROM posts
WHERE id < 83
ORDER BY id DESC
LIMIT 20;

-- کرسر '83' سے پہلے 20 ریکارڈ حاصل کریں (پیچھے)
SELECT id, title, created_at
FROM posts
WHERE id > 83
ORDER BY id ASC
LIMIT 20;

کرسر فارمیٹ

کرسر سادہ (ایک ID قدر) یا پیچیدہ (متعدد فیلڈز پر مشتمل) ہو سکتا ہے۔ سادہ کرسرز ریکارڈ کی بنیادی کلید ہوتے ہیں، مثال کے طور پر، خودکار اضافہ id یا UUID۔ مرکب کرسرز غیر منفرد فیلڈز کے مطابق ترتیب دینے کے لیے استعمال ہوتے ہیں، مثال کے طور پر (created_at, id)، جہاں id ایک جیسے ٹائم سٹیمپ پر انفرادیت کو یقینی بناتا ہے۔

ایک عام API فارمیٹ base64-انکوڈڈ سٹرنگ کے طور پر کرسر ہے۔ سرور کرسر کو ڈی کوڈ کرتا ہے، قدر نکالتا ہے، اور SQL استفسار بناتا ہے۔ Base64 انکوڈنگ کرسر کی داخلی ساخت کو کلائنٹ سے چھپاتی ہے اور پسماندہ مطابقت کو توڑے بغیر فارمیٹ تبدیل کرنے کی اجازت دیتی ہے۔ کلائنٹ جواب کے endCursor فیلڈ میں کرسرز وصول کرتا ہے اور انہیں اگلی درخواست میں سٹرنگ کے طور پر منتقل کرتا ہے۔

آگے اور پیچھے نیویگیشن

کرسر صفحہ بندی دو طرفہ نیویگیشن کی حمایت کرتی ہے۔ آگے بڑھنے (next) کے لیے موجودہ صفحہ کے آخری عنصر کا کرسر استعمال ہوتا ہے؛ پیچھے (previous) کے لیے پہلے عنصر کا کرسر۔ درخواست میں after اور before پیرامیٹرز سمت کا تعین کرتے ہیں: after کرسر کے بعد ریکارڈ لیتا ہے، before کرسر سے پہلے ریکارڈ لیتا ہے۔

Cursor بمقابلہ Offset صفحہ بندی

کرسر اور Offset صفحہ بندی کے درمیان انتخاب API ڈیزائن کرتے وقت اہم تعمیراتی فیصلوں میں سے ایک ہے۔ ہر طریقہ میں طاقت اور کمزوریاں ہیں جو اس کی اطلاقیت کا تعین کرتی ہیں۔ Cursor pagination متحرک ڈیٹا والے منظرناموں میں جیتتا ہے؛ Offset صوابدیدی نیویگیشن والے منظرناموں میں جیتتا ہے۔

خصوصیتCursorOffset
اندراج پر استحکاماعلی (کوئی نقل نہیں)کم (صفحات کی منتقلی)
بڑے سیٹوں پر کارکردگیO(log n) — مستحکمO(n) — بڑھنے سے گھٹتی ہے
صفحہ نمبر کے ذریعے نیویگیشننہیںہاں (page=5)
نفاذ کی پیچیدگیدرمیانیکم
REST حمایتcursor/before/afterpage/offset
GraphQL حمایتRelay معیارتجویز نہیں کیا جاتا

Offset بڑے پیمانے پر کیوں ناکام ہوتا ہے

Offset صفحہ بندی OFFSET مقام تک مکمل ٹیبل سکین کرتی ہے۔ offset=100000 پر، ڈیٹابیس 100000 قطاریں پڑھتا اور چھوڑتا ہے، چاہے LIMIT 20 ہی کیوں نہ ہو۔ MySQL اور PostgreSQL OFFSET کو بہتر نہیں کر سکتے — یہ SQL میں LIMIT/OFFSET کے نفاذ کی ایک خصوصیت ہے۔ کرسر صفحہ بندی B-tree انڈیکس استعمال کرتی ہے جو O(log n) میں مقام ڈھونڈتا ہے۔

Offset کا ایک اضافی مسئلہ پیچھے کی طرف صفحہ بندی کرتے وقت ریکارڈز کا “چھوڑنا” ہے۔ اگر کسی صارف نے صفحہ 5 لوڈ کیا اور اسی لمحے نئے ریکارڈز شامل ہو گئے، تو صفحہ 6 کی درخواست کرنے پر وہ صفحہ 5 کا ریکارڈ دوبارہ دیکھیں گے یا نئے ریکارڈز سے محروم ہو جائیں گے۔ Cursor pagination اس منظرنامے کو مکمل طور پر ختم کرتا ہے: کرسر سیٹ میں ایک مخصوص جگہ کی طرف اشارہ کرتا ہے اور اندراج مقام کو تبدیل نہیں کرتا۔

Cursor Pagination کا نفاذ

آئیے بیک اینڈ (Kotlin + Spring) اور کلائنٹ (Android + Retrofit) پر کرسر صفحہ بندی کے نفاذ کو دیکھتے ہیں۔ سرور after، before، limit پیرامیٹرز قبول کرتا ہے اور کرسرز اور pageInfo کے ساتھ ریکارڈز کی فہرست واپس کرتا ہے۔ ایک عام جواب میں صفحہ بندی UI کے انتظام کے لیے hasNextPage اور hasPreviousPage ہوتا ہے۔

kotlin
@GetMapping("/posts")
fun getPosts(
    @RequestParam after: Long?,
    @RequestParam(defaultValue = "20") limit: Int
): CursorResponse<Post> {
    val cursor = after ?: Long.MAX_VALUE
    val posts = repository.findByIdLessThanOrderByIdDesc(
        cursor, PageRequest.of(0, limit)
    )
    val endCursor = posts.lastOrNull()?.id
    return CursorResponse(
        data = posts,
        pageInfo = PageInfo(
            hasNextPage = posts.size == limit,
            endCursor = endCursor
        )
    )
}

Android پر کلائنٹ کا نفاذ

کلائنٹ پر، کرسر صفحہ بندی Paging 3 سے PagingSource کے ذریعے نافذ کی جاتی ہے، جہاں کلید ایک کرسر (Long) ہے۔ PagingSource.load LoadParams.key وصول کرتا ہے — آخری لوڈ کردہ ریکارڈ کا کرسر۔ LoadResult.Page ڈیٹا اور nextKey — اگلے صفحے کے لیے کرسر — واپس کرتا ہے۔ جب nextKey = null ہو، صفحہ بندی مکمل ہو جاتی ہے۔

kotlin
// Retrofit API
interface PostApi {
    @GET("posts")
    suspend fun getPosts(
        @Query("after") after: Long?,
        @Query("limit") limit: Int = 20
    ): CursorResponse<Post>
}

// کرسر کلید کے ساتھ PagingSource
class PostPagingSource(
    private val api: PostApi
) : PagingSource<Long, Post>() {

    override suspend fun load(
        params: LoadParams<Long>
    ): LoadResult<Long, Post> = try {
        val response = api.getPosts(
            after = params.key,
            limit = params.loadSize
        )
        val nextKey = response.pageInfo.endCursor
        LoadResult.Page(
            data = response.data,
            prevKey = null,
            nextKey = nextKey
        )
    } catch (e: Exception) {
        LoadResult.Error(e)
    }
}

Relay کے ذریعے GraphQL کا نفاذ

GraphQL میں، کرسر صفحہ بندی Relay Connection پیٹرن کے ذریعے نافذ کی جاتی ہے۔ ہر قسم میں ایک Connection (pageInfo اور edges کے ساتھ) اور ایک Edge (node + cursor) ہوتا ہے۔ استفسار first، after، last، before پیرامیٹرز منتقل کرتا ہے۔ سرور کرسرز کے ساتھ edges کی صف اور hasNextPage/hasPreviousPage کے ساتھ pageInfo واپس کرتا ہے۔

Cursor Pagination کب استعمال کریں

کرسر صفحہ بندی متحرک ڈیٹا کے ساتھ کام کرنے والے APIs کے لیے تجویز کی جاتی ہے جہاں ریکارڈز بار بار شامل یا حذف کیے جاتے ہیں۔ کلاسک مثالیں: سوشل نیٹ ورک میں نیوز فیڈ، چیٹ پیغامات، لین دین کی تاریخ، پوسٹ کے تبصرے۔ ان تمام منظرناموں میں، مستقل مزاجی اور نقلوں کی عدم موجودگی اہم ہے۔

  • چیٹ اور میسنجر — ہر نیا پیغام فہرست کے اوپر شامل کیا جاتا ہے۔ Offset صفحہ بندی ہر نئے پیغام کے ساتھ بگڑ جاتی ہے۔
  • سوشل نیٹ ورکس اور فیڈز — پوسٹس مسلسل شائع ہوتی ہیں۔ کرسر صفحہ بندی اس بات کی ضمانت دیتی ہے کہ صارف ایک بھی پوسٹ سے محروم نہ ہو۔
  • آرڈر اور لین دین کی تاریخ — ڈیٹا کم کثرت سے تبدیل ہوتا ہے، لیکن مالیاتی رپورٹنگ کے لیے مستقل مزاجی اہم ہے۔
  • بڑے ڈیٹا والیوم کے APIs — لاکھوں ریکارڈز۔ Cursor pagination کارکردگی برقرار رکھتا ہے جہاں Offset سست ہونے لگتا ہے۔
  • GraphQL APIs — Relay معیار تصریح کی تعمیل کے لیے کرسر پر مبنی صفحہ بندی کا تقاضا کرتا ہے۔
  • لامحدود اسکرول والی موبائل ایپس — صارف نیچے اسکرول کرکے نئے بیچ لوڈ کرتا ہے۔ کرسر طریقہ نقلوں کے بغیر ایک ہموار صارف تجربہ فراہم کرتا ہے۔

کرسر صفحہ بندی کب موزوں نہیں ہے

ایسے منظرنامے ہیں جہاں Offset صفحہ بندی زیادہ آسان ہے: ایڈمن پینلز جہاں صفحہ نمبر کے ذریعے نیویگیشن کی ضرورت ہے؛ صفحہ بندی کے ساتھ تلاش جہاں نتائج تبدیل ہو سکتے ہیں؛ رپورٹس اور تجزیہ جہاں صفحہ 5 کے لیے ایک مقررہ لنک کی ضرورت ہے۔ ان صورتوں میں، کرسر کے فوائد نفاذ کی پیچیدگی سے زیادہ نہیں ہوتے۔

کرسر صفحہ بندی صوابدیدی صفحہ پر “چھلانگ” لگانے کی حمایت نہیں کرتی — صارف “صفحہ 5” پر کلک کرکے وہاں نہیں جا سکتا۔ یہ ایک تعمیراتی حد ہے: صفحات کی کل تعداد گننا علیحدہ COUNT استفسار کی ضرورت ہے، جو بڑی ٹیبلز کے لیے مہنگا ہو سکتا ہے۔ ایسے معاملات میں ایک ملا جلا طریقہ: ڈیٹا کے لیے کرسر + صفحہ بندی کے لیے count۔

اکثر پوچھے گئے سوالات

Cursor Pagination میں کرسر کیا ہے؟

کرسر ایک منفرد ریکارڈ شناخت کنندہ ہے جو ڈیٹا سیٹ میں ایک مقام کی طرف اشارہ کرتا ہے۔ یہ سادہ (ایک ریکارڈ ID) یا مرکب (متعدد فیلڈز) ہو سکتا ہے۔ کلائنٹ صفحہ کے آخری ریکارڈ کا کرسر وصول کرتا ہے اور اگلا بیچ حاصل کرنے کے لیے اسے اگلی درخواست میں منتقل کرتا ہے۔

Cursor Pagination Offset سے بہتر کیوں ہے؟

Cursor pagination نئے ریکارڈز شامل ہونے پر منتقلی کا شکار نہیں ہوتا — ہر عنصر بالکل ایک صفحہ میں آتا ہے۔ یہ پہلی n قطاروں کو اسکین کرنے کے بجائے انڈیکس استعمال کرکے بڑے والیوم پر رفتار بھی برقرار رکھتا ہے۔ Offset آسان ہے لیکن متحرک ڈیٹا کے لیے غیر مستحکم ہے۔

کیا GraphQL کے بغیر کرسر صفحہ بندی نافذ کی جا سکتی ہے؟

ہاں، کرسر صفحہ بندی GraphQL سے منسلک نہیں ہے۔ اسے کسی بھی REST API میں کرسر کو استفساری پیرامیٹر ?after=83&limit=20 کے طور پر منتقل کرکے نافذ کیا جا سکتا ہے۔ جواب میں endCursor اور hasNextPage کے ساتھ pageInfo ہونا چاہیے — یہ کلائنٹ کو داخلی کرسر ساخت جانے بغیر لوڈنگ کو منظم کرنے کی اجازت دیتا ہے۔

کون سا کرسر استعمال کریں — ID، UUID یا timestamp؟

خودکار اضافہ ID بہترین انتخاب ہے: یکساں طور پر بڑھتا ہے، تبدیل نہیں ہوتا، مؤثر طریقے سے انڈیکس ہوتا ہے۔ UUID v7 (وقت کے مطابق ترتیب شدہ) بھی موزوں ہے۔ ٹائم سٹیمپ ایک ہی وقت میں نقل پیدا کر سکتے ہیں، لہٰذا اسے ID کے ساتھ ملائیں: (created_at, id) کرسر کی انفرادیت کو یقینی بنانے کے لیے۔

کرسر صفحہ بندی کے ساتھ صفحات کی کل تعداد کیسے معلوم کریں؟

کرسر صفحہ بندی صفحات کی کل تعداد فراہم نہیں کرتی — یہ اس کی حد ہے۔ اگر آپ کو کل معلومات کی ضرورت ہے تو ایک ہی فلٹرز کے ساتھ علیحدہ COUNT استفسار چلائیں۔ بڑی ٹیبلز کے لیے، EXPLAIN کے ذریعے تخمینی گنتی یا تجزیات سے کیشڈ کل استعمال کریں۔

خلاصہ

  • Cursor Pagination ایک صفحہ بندی کا طریقہ ہے جس میں آفسیٹ کے بجائے منفرد ریکارڈ شناخت کنندہ کے ذریعے نیویگیشن ہوتی ہے۔
  • کرسر اندراج پر سیٹ کے استحکام کی ضمانت دیتا ہے: نئے ریکارڈ پہلے سے لوڈ کردہ صفحات کو منتقل نہیں کرتے۔
  • کارکردگی B-tree انڈیکس کے استعمال کی بدولت بڑے ڈیٹا والیوم پر اعلی (O(log n)) رہتی ہے۔
  • Cursor pagination متحرک ڈیٹا کے لیے موزوں ہے: چیٹس، نیوز فیڈز، لین دین، تبصرے۔
  • بنیادی حد صفحہ نمبر کے ذریعے نیویگیشن کی کمی اور صوابدیدی صفحہ پر چھلانگ لگانے میں ناکامی ہے۔
  • نفاذ کرسر کے بعد WHERE id، after/before پیرامیٹرز اور جواب میں pageInfo استعمال کرتا ہے۔
  • معیار — Relay Connection GraphQL، لیکن کرسر پیرامیٹرز والے REST APIs بھی وسیع پیمانے پر استعمال ہوتے ہیں۔

ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے

IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں