پرش به محتویات

صفحه‌بندی و جستجو (Pagination & Filtering)

مقدمه

تمامی اندپوینت‌های لیست‌گیری از سیستم صفحه‌بندی و فیلترینگ پیشرفته پشتیبانی می‌کنند. این امکان به کلاینت‌ها اجازه می‌دهد داده‌ها را به صورت بهینه دریافت و مدیریت کنند.

ساختار پاسخ استاندارد

فرمت

{
  "heads": {
    "uid": "شناسه",
    "created_at": "تاریخ ایجاد",
    "updated_at": "تاریخ به‌روزرسانی"
  },
  "items": [
    {
      "uid": "item_1",
      "field1": "value1",
      "field2": "value2"
    },
    {
      "uid": "item_2",
      "field1": "value1",
      "field2": "value2"
    }
  ],
  "total": 100,
  "offset": 0,
  "limit": 10
}

توضیحات فیلدها

heads

یک آبجکت که کلیدهای (فیلدهای) موجود در هر آیتم از items را تعریف می‌کند. این برای اعتبارسنجی و مستندسازی داینامیک استفاده می‌شود.

مثال:

"heads": {
  "uid": "شناسه منحصر به فرد",
  "symbol": "نماد معاملاتی",
  "side": "جهت سفارش",
  "price": "قیمت",
  "quantity": "حجم"
}

items

آرایه‌ای از آیتم‌های نتیجه که با پارامترهای صفحه‌بندی فیلتر شده‌اند.

total

تعداد کل آیتم‌های موجود بدون در نظر گرفتن صفحه‌بندی.

offset

شروع صفحه‌بندی (تعداد آیتم‌های رد شده از ابتدا).

limit

حداکثر تعداد آیتم‌های در هر صفحه.

پارامترهای صفحه‌بندی

offset

  • نوع: integer

  • پیش‌فرض: 0

  • حداقل: 0

  • کاربرد: مشخص می‌کند از کدام آیتم شروع شود

مثال:

# شروع از آیتم 21
GET /api/exchange/v1/orders?offset=20&limit=10

limit

  • نوع: integer

  • پیش‌فرض: 10

  • حداقل: 1

  • حداکثر: 100

  • کاربرد: مشخص می‌کند چند آیتم در هر صفحه نمایش داده شود

مثال:

# 20 آیتم در هر صفحه
GET /api/exchange/v1/orders?offset=0&limit=20

فیلترهای تاریخ

created_at_from

  • نوع: string (ISO 8601)

  • کاربرد: فیلتر آیتم‌های ایجاد شده از این تاریخ

مثال:

GET /api/exchange/v1/orders?created_at_from=2025-12-01T00:00:00Z

created_at_to

  • نوع: string (ISO 8601)

  • کاربرد: فیلتر آیتم‌های ایجاد شده تا این تاریخ

مثال:

GET /api/exchange/v1/orders?created_at_to=2025-12-31T23:59:59Z

ترکیب فیلترهای تاریخ

GET /api/exchange/v1/orders?created_at_from=2025-12-01T00:00:00Z&created_at_to=2025-12-31T23:59:59Z

فیلترهای اختصاصی هر ریسورس

User API

# فیلتر بر اساس وضعیت
GET /api/user/v1/users?status=active

# فیلتر بر اساس نقش
GET /api/user/v1/users?role=trader

# جستجو در نام یا ایمیل
GET /api/user/v1/users?search=john

Wallet API

# فیلتر بر اساس نوع کیف پول
GET /api/accounting/v1/wallets?type=spot

# فیلتر بر اساس موجودی
GET /api/accounting/v1/wallets?min_balance=1000000

Exchange API - Orders

# فیلتر بر اساس کاربر
GET /api/exchange/v1/orders?user_id=user_123

# فیلتر بر اساس نماد
GET /api/exchange/v1/orders?symbol=BTC-IRR

# فیلتر بر اساس جهت
GET /api/exchange/v1/orders?side=buy

# فیلتر بر اساس وضعیت
GET /api/exchange/v1/orders?status=active

# ترکیب چند فیلتر
GET /api/exchange/v1/orders?user_id=user_123&symbol=BTC-IRR&status=active

Exchange API - Trades

# فیلتر بر اساس نماد
GET /api/exchange/v1/trades?symbol=BTC-IRR

# فیلتر بر اساس کاربر
GET /api/exchange/v1/trades?user_id=user_123

# فیلتر بر اساس کیف پول
GET /api/exchange/v1/trades?wallet_id=wallet_456

# فیلتر بر اساس سفارش
GET /api/exchange/v1/trades?order_id=order_789

# فیلتر بر اساس جهت
GET /api/exchange/v1/trades?order_side=buy

نمونه‌های کامل

نمونه 1: دریافت لیست سفارشات با فیلتر کامل

درخواست:

curl -X GET "{BASE_URL}/api/exchange/v1/orders?\
user_id=user_123&\
symbol=BTC-IRR&\
side=buy&\
status=active&\
created_at_from=2025-12-01T00:00:00Z&\
created_at_to=2025-12-31T23:59:59Z&\
offset=0&\
limit=10" \
  -H "Authorization: Bearer $JWT_TOKEN"

پاسخ موفق (200 OK):

{
  "heads": {
    "uid": "شناسه",
    "user_id": "کاربر",
    "symbol": "نماد",
    "side": "جهت",
    "type": "نوع",
    "price": "قیمت",
    "quantity": "حجم",
    "status": "وضعیت",
    "created_at": "تاریخ ایجاد"
  },
  "items": [
    {
      "uid": "ord_001",
      "user_id": "user_123",
      "symbol": "BTC-IRR",
      "side": "buy",
      "type": "limit",
      "price": "1000000000",
      "quantity": "0.5",
      "status": "active",
      "created_at": "2025-12-15T10:30:00Z"
    },
    {
      "uid": "ord_002",
      "user_id": "user_123",
      "symbol": "BTC-IRR",
      "side": "buy",
      "type": "limit",
      "price": "999000000",
      "quantity": "0.3",
      "status": "active",
      "created_at": "2025-12-16T14:20:00Z"
    }
  ],
  "total": 25,
  "offset": 0,
  "limit": 10
}

نمونه 2: صفحه دوم با 20 آیتم

درخواست:

curl -X GET "{BASE_URL}/api/exchange/v1/orders?offset=20&limit=20" \
  -H "Authorization: Bearer $JWT_TOKEN"

پاسخ موفق (200 OK):

{
  "heads": {
    "uid": "شناسه",
    "symbol": "نماد",
    "side": "جهت",
    "status": "وضعیت"
  },
  "items": [
    {
      "uid": "ord_021",
      "symbol": "ETH-IRR",
      "side": "sell",
      "status": "filled"
    },
    {
      "uid": "ord_022",
      "symbol": "BTC-IRR",
      "side": "buy",
      "status": "active"
    }
    // ... 18 آیتم دیگر
  ],
  "total": 100,
  "offset": 20,
  "limit": 20
}

نمونه 3: لیست خالی (بدون نتیجه)

درخواست:

curl -X GET "{BASE_URL}/api/exchange/v1/orders?status=nonexistent_status" \
  -H "Authorization: Bearer $JWT_TOKEN"

پاسخ موفق (200 OK):

{
  "heads": {
    "uid": "شناسه",
    "symbol": "نماد",
    "side": "جهت",
    "status": "وضعیت"
  },
  "items": [],
  "total": 0,
  "offset": 0,
  "limit": 10
}

نمونه 4: درخواست با offset بزرگتر از total

درخواست:

curl -X GET "{BASE_URL}/api/exchange/v1/orders?offset=1000&limit=10" \
  -H "Authorization: Bearer $JWT_TOKEN"

پاسخ موفق (200 OK):

{
  "heads": {
    "uid": "شناسه",
    "symbol": "نماد"
  },
  "items": [],
  "total": 100,
  "offset": 1000,
  "limit": 10
}

نمونه‌های ناموفق

نمونه 1: limit بیشتر از حداکثر

درخواست:

curl -X GET "{BASE_URL}/api/exchange/v1/orders?limit=500" \
  -H "Authorization: Bearer $JWT_TOKEN"

پاسخ خطا (422 Unprocessable Entity):

{
  "detail": [
    {
      "loc": ["query", "limit"],
      "msg": "ensure this value is less than or equal to 100",
      "type": "value_error.number.not_le",
      "ctx": {"limit_value": 100}
    }
  ]
}

نمونه 2: offset منفی

درخواست:

curl -X GET "{BASE_URL}/api/exchange/v1/orders?offset=-1" \
  -H "Authorization: Bearer $JWT_TOKEN"

پاسخ خطا (422 Unprocessable Entity):

{
  "detail": [
    {
      "loc": ["query", "offset"],
      "msg": "ensure this value is greater than or equal to 0",
      "type": "value_error.number.not_ge",
      "ctx": {"limit_value": 0}
    }
  ]
}

نمونه 3: فرمت تاریخ نامعتبر

درخواست:

curl -X GET "{BASE_URL}/api/exchange/v1/orders?created_at_from=2025/12/01" \
  -H "Authorization: Bearer $JWT_TOKEN"

پاسخ خطا (422 Unprocessable Entity):

{
  "detail": [
    {
      "loc": ["query", "created_at_from"],
      "msg": "invalid datetime format, expected ISO 8601",
      "type": "value_error.datetime"
    }
  ]
}

نمونه 4: پارامتر نامعتبر

درخواست:

curl -X GET "{BASE_URL}/api/exchange/v1/orders?invalid_param=value" \
  -H "Authorization: Bearer $JWT_TOKEN"

پاسخ خطا (422 Unprocessable Entity):

{
  "detail": [
    {
      "loc": ["query", "invalid_param"],
      "msg": "extra fields not permitted",
      "type": "value_error.extra"
    }
  ]
}

الگوریتم صفحه‌بندی

محاسبه صفحات

# تعداد کل صفحات
total_pages = ceil(total / limit)

# صفحه فعلی
current_page = floor(offset / limit) + 1

# صفحه بعدی
next_offset = offset + limit
next_page = current_page + 1

# صفحه قبلی
prev_offset = max(0, offset - limit)
prev_page = max(1, current_page - 1)

مثال محاسبه

total = 100
offset = 20
limit = 10

total_pages = ceil(100 / 10) = 10
current_page = floor(20 / 10) + 1 = 3
next_offset = 20 + 10 = 30
prev_offset = max(0, 20 - 10) = 10

چک‌لیست استفاده

قبل از هر درخواست:

  • [ ] offset و limit تنظیم شده‌اند

  • [ ] فیلترهای تاریخ در صورت نیاز اضافه شده‌اند

  • [ ] فیلترهای اختصاصی ریسورس استفاده شده‌اند

  • [ ] پارامترها معتبر هستند

  • [ ] توکن احراز هویت ارسال شده است

خلاصه

  • صفحه‌بندی: offset و limit (حداکثر 100)

  • فیلتر تاریخ: created_at_from و created_at_to

  • فیلتر اختصاصی: بر اساس هر ریسورس

  • پاسخ استاندارد: شامل heads, items, total, offset, limit


بعدی: مطالعه خطاها و پاسخ‌های ناموفق