ذخیره داده ها

راه‌های صرفه‌جویی در مصرف داده

قرار دادن نوشتن یا جایگزینی داده‌ها در یک مسیر تعریف‌شده ، مانند fireblog/users/user1/<data>
پچ به‌روزرسانی برخی از کلیدها برای یک مسیر تعریف‌شده بدون جایگزینی تمام داده‌ها.
پست به لیستی از داده‌ها در پایگاه داده Firebase خود اضافه کنید . هر بار که یک درخواست POST ارسال می‌کنیم، کلاینت Firebase یک کلید منحصر به فرد مانند fireblog/users/<unique-id>/<data> ایجاد می‌کند.
حذف داده‌ها را از مرجع پایگاه داده Firebase مشخص شده حذف کنید.

نوشتن داده‌ها با PUT

عملیات نوشتن پایه از طریق REST API، PUT است. برای نشان دادن ذخیره داده‌ها، یک برنامه وبلاگ‌نویسی با پست‌ها و کاربران خواهیم ساخت. تمام داده‌های برنامه ما در مسیر `fireblog`، در آدرس پایگاه داده Firebase `https://docs-examples.firebaseio.com/fireblog` ذخیره خواهند شد.

بیایید با ذخیره برخی از داده‌های کاربر در پایگاه داده Firebase خود شروع کنیم. ما هر کاربر را با یک نام کاربری منحصر به فرد ذخیره خواهیم کرد و همچنین نام کامل و تاریخ تولد آنها را نیز ذخیره خواهیم کرد. از آنجایی که هر کاربر یک نام کاربری منحصر به فرد خواهد داشت، منطقی است که از PUT به جای POST استفاده کنیم، زیرا ما از قبل کلید را داریم و نیازی به ایجاد آن نداریم.

با استفاده از PUT می‌توانیم یک رشته، عدد، بولی، آرایه یا هر شیء JSON را در پایگاه داده Firebase خود بنویسیم. در این حالت، یک شیء به آن ارسال می‌کنیم:

curl -X PUT -d '{
  "alanisawesome": {
    "name": "Alan Turing",
    "birthday": "June 23, 1912"
  }
}' 'https://docs-examples.firebaseio.com/fireblog/users.json'

وقتی یک شیء JSON در پایگاه داده ذخیره می‌شود، ویژگی‌های شیء به طور خودکار به مکان‌های فرزند به صورت تو در تو نگاشت می‌شوند. اگر به گره تازه ایجاد شده برویم، مقدار "آلن تورینگ" را خواهیم دید. همچنین می‌توانیم داده‌ها را مستقیماً در یک مکان فرزند ذخیره کنیم:

curl -X PUT -d '"Alan Turing"' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/name.json'
curl -X PUT -d '"June 23, 1912"' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/birthday.json'

دو مثال بالا - نوشتن مقدار همزمان به عنوان یک شیء و نوشتن جداگانه آنها در مکان‌های فرزند - منجر به ذخیره داده‌های یکسان در پایگاه داده Firebase ما می‌شوند:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing"
    }
  }
}

یک درخواست موفق با کد وضعیت HTTP 200 OK نشان داده می‌شود و پاسخ شامل داده‌هایی است که ما در پایگاه داده نوشته‌ایم. مثال اول فقط یک رویداد را در کلاینت‌هایی که داده‌ها را مشاهده می‌کنند، فعال می‌کند، در حالی که مثال دوم دو رویداد را فعال می‌کند. توجه به این نکته مهم است که اگر داده‌ها از قبل در مسیر کاربران وجود داشته باشند، رویکرد اول آن را بازنویسی می‌کند، اما روش دوم فقط مقدار هر گره فرزند جداگانه را تغییر می‌دهد و سایر فرزندان را بدون تغییر باقی می‌گذارد. PUT معادل set() در SDK جاوا اسکریپت ما است.

به‌روزرسانی داده‌ها با PATCH

با استفاده از یک درخواست PATCH ، می‌توانیم فرزندان خاصی را در یک مکان بدون بازنویسی داده‌های موجود به‌روزرسانی کنیم. بیایید لقب تورینگ را با یک درخواست PATCH به داده‌های کاربر او اضافه کنیم:

curl -X PATCH -d '{
  "nickname": "Alan The Machine"
}' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'

درخواست بالا، nickname بدون حذف name یا فرزندان birthday ، برای شیء alanisawesome ما می‌نویسد. توجه داشته باشید که اگر به جای آن، یک درخواست PUT ارسال می‌کردیم، name و birthday حذف می‌شدند زیرا در درخواست گنجانده نشده بودند. داده‌های موجود در پایگاه داده Firebase ما اکنون به این شکل است:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing",
      "nickname": "Alan The Machine"
    }
  }
}

یک درخواست موفق با کد وضعیت HTTP 200 OK نشان داده می‌شود و پاسخ شامل داده‌های به‌روزرسانی‌شده نوشته‌شده در پایگاه داده خواهد بود.

فایربیس همچنین از به‌روزرسانی‌های چندمسیره پشتیبانی می‌کند. این بدان معناست که PATCH اکنون می‌تواند مقادیر را در چندین مکان در پایگاه داده فایربیس شما به طور همزمان به‌روزرسانی کند، یک ویژگی قدرتمند که به شما کمک می‌کند داده‌های خود را از حالت نرمال خارج کنید . با استفاده از به‌روزرسانی‌های چندمسیره، می‌توانیم همزمان به آلن و گریس نام مستعار اضافه کنیم:

curl -X PATCH -d '{
  "alanisawesome/nickname": "Alan The Machine",
  "gracehopper/nickname": "Amazing Grace"
}' \
  'https://docs-examples.firebaseio.com/fireblog/users.json'

بعد از این به‌روزرسانی، لقب‌های آلن و گریس اضافه شد:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing",
      "nickname": "Alan The Machine"
    },
    "gracehop": {
      "date_of_birth": "December 9, 1906",
      "full_name": "Grace Hopper",
      "nickname": "Amazing Grace"
    }
  }
}

توجه داشته باشید که تلاش برای به‌روزرسانی اشیاء با نوشتن اشیاء به همراه مسیرهای گنجانده شده، منجر به رفتار متفاوتی خواهد شد. بیایید نگاهی به این بیندازیم که اگر به جای آن سعی کنیم گریس و آلن را به این روش به‌روزرسانی کنیم، چه اتفاقی می‌افتد:

curl -X PATCH -d '{
  "alanisawesome": {"nickname": "Alan The Machine"},
  "gracehopper": {"nickname": "Amazing Grace"}
}' \
  'https://docs-examples.firebaseio.com/fireblog/users.json'

این منجر به رفتار متفاوتی می‌شود، یعنی کل گره /fireblog/users را بازنویسی می‌کند:

{
  "users": {
    "alanisawesome": {
      "nickname": "Alan The Machine"
    },
    "gracehop": {
      "nickname": "Amazing Grace"
    }
  }
}

به‌روزرسانی داده‌ها با درخواست‌های شرطی

شما می‌توانید از درخواست‌های شرطی، معادل REST تراکنش‌ها، برای به‌روزرسانی داده‌ها بر اساس وضعیت موجودشان استفاده کنید. به عنوان مثال، اگر می‌خواهید یک شمارنده رأی مثبت را افزایش دهید و می‌خواهید مطمئن شوید که تعداد آنها به طور دقیق چندین رأی مثبت همزمان را منعکس می‌کند، از یک درخواست شرطی برای نوشتن مقدار جدید در شمارنده استفاده کنید. به جای دو نوشتن که شمارنده را به همان عدد تغییر می‌دهند، یکی از درخواست‌های نوشتن با شکست مواجه می‌شود و سپس می‌توانید درخواست را با مقدار جدید دوباره امتحان کنید.
  1. برای انجام یک درخواست شرطی در یک مکان، شناسه منحصر به فرد داده‌های فعلی در آن مکان یا ETag را دریافت کنید. اگر داده‌ها در آن مکان تغییر کنند، ETag نیز تغییر می‌کند. می‌توانید ETag را با هر روشی غیر از PATCH درخواست کنید. مثال زیر از یک درخواست GET استفاده می‌کند.
    curl -i 'https://test.example.com/posts/12345/upvotes.json' -H 'X-Firebase-ETag: true'
    فراخوانی ETag در هدر، ETag مربوط به مکان مشخص شده در پاسخ HTTP را برمی‌گرداند.
    HTTP/1.1 200 OK
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    ETag: [ETAG_VALUE]
    Cache-Control: no-cache
    
    10 // Current value of the data at the specified location
  2. ETag برگردانده شده را در درخواست PUT یا DELETE بعدی خود قرار دهید تا داده‌هایی که به طور خاص با آن مقدار ETag مطابقت دارند، به‌روزرسانی شوند. با پیروی از مثال ما، برای به‌روزرسانی شمارنده به ۱۱ یا ۱ واحد بزرگتر از مقدار اولیه واکشی شده ۱۰، و شکست درخواست در صورت عدم مطابقت مقدار، از کد زیر استفاده کنید:
    curl -iX PUT -d '11' 'https://[PROJECT_ID].firebaseio.com/posts/12345/upvotes.json' -H 'if-match:[ETAG_VALUE]'
    اگر مقدار داده در مکان مشخص شده هنوز 10 باشد، ETag در درخواست PUT مطابقت دارد و درخواست با موفقیت انجام می‌شود و 11 در پایگاه داده نوشته می‌شود.
    HTTP/1.1 200 OK
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    Cache-Control: no-cache
    
    11 // New value of the data at the specified location, written by the conditional request
    اگر مکان دیگر با ETag مطابقت نداشته باشد، که ممکن است در صورت نوشتن مقدار جدید توسط کاربر دیگری در پایگاه داده رخ دهد، درخواست بدون نوشتن در مکان با شکست مواجه می‌شود. پاسخ برگشتی شامل مقدار جدید و ETag است.
    HTTP/1.1 412 Precondition Failed
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    ETag: [ETAG_VALUE]
    Cache-Control: no-cache
    
    12 // New value of the data at the specified location
  3. اگر تصمیم به تلاش مجدد برای درخواست دارید، از اطلاعات جدید استفاده کنید. Realtime Database به طور خودکار درخواست‌های شرطی که با شکست مواجه شده‌اند را دوباره امتحان نمی‌کند. با این حال، می‌توانید از مقدار جدید و ETag برای ساخت یک درخواست شرطی جدید با اطلاعات برگردانده شده توسط پاسخ ناموفق استفاده کنید.

درخواست‌های شرطی مبتنی بر REST، استاندارد HTTP if-match را پیاده‌سازی می‌کنند. با این حال، آنها از جهات زیر با این استاندارد متفاوت هستند:

  • شما فقط می‌توانید یک مقدار ETag را برای هر درخواست if-match ارائه دهید، نه چندین مقدار.
  • در حالی که استاندارد پیشنهاد می‌کند ETagها با تمام درخواست‌ها برگردانده شوند، Realtime Database فقط ETagهایی را برمی‌گرداند که شامل هدر X-Firebase-ETag باشند. این امر هزینه‌های صدور صورتحساب برای درخواست‌های استاندارد را کاهش می‌دهد.

درخواست‌های شرطی همچنین ممکن است کندتر از درخواست‌های معمولی REST باشند.

ذخیره لیست داده‌ها

برای تولید یک کلید منحصر به فرد مبتنی بر مهر زمانی برای هر فرزندی که به مرجع پایگاه داده Firebase اضافه می‌شود، می‌توانیم یک درخواست POST ارسال کنیم. برای مسیر users ، منطقی بود که کلیدهای خودمان را تعریف کنیم زیرا هر کاربر یک نام کاربری منحصر به فرد دارد. اما وقتی کاربران پست‌های وبلاگ را به برنامه اضافه می‌کنند، از یک درخواست POST برای تولید خودکار یک کلید برای هر پست وبلاگ استفاده خواهیم کرد:

curl -X POST -d '{
  "author": "alanisawesome",
  "title": "The Turing Machine"
}' 'https://docs-examples.firebaseio.com/fireblog/posts.json'

مسیر posts ما اکنون داده‌های زیر را دارد:

{
  "posts": {
    "-JSOpn9ZC54A4P4RoqVa": {
      "author": "alanisawesome",
      "title": "The Turing Machine"
    }
  }
}

توجه داشته باشید که کلید -JSOpn9ZC54A4P4RoqVa به طور خودکار برای ما ایجاد شده است زیرا ما از درخواست POST استفاده کردیم. یک درخواست موفق با کد وضعیت HTTP 200 OK نشان داده می‌شود و پاسخ شامل کلید داده‌های جدیدی است که اضافه شده‌اند:

{"name":"-JSOpn9ZC54A4P4RoqVa"}

حذف داده‌ها

برای حذف داده‌ها از پایگاه داده، می‌توانیم یک درخواست DELETE به همراه URL مسیری که می‌خواهیم داده‌ها را از آن حذف کنیم، ارسال کنیم. دستور زیر آلن را از مسیر users ما حذف می‌کند:

curl -X DELETE \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'

یک درخواست DELETE موفق با کد وضعیت HTTP 200 OK و پاسخی حاوی JSON null نشان داده می‌شود.

پارامترهای URI

REST API هنگام نوشتن داده‌ها در پایگاه داده، پارامترهای URI زیر را می‌پذیرد:

نویسنده

پارامتر درخواست auth امکان دسترسی به داده‌های محافظت‌شده توسط Firebase Realtime Database Security Rules را فراهم می‌کند و توسط همه انواع درخواست‌ها پشتیبانی می‌شود. این آرگومان می‌تواند رمز برنامه Firebase یا یک توکن احراز هویت باشد که در بخش احراز هویت کاربر به آن خواهیم پرداخت. در مثال زیر، یک درخواست POST با پارامتر auth ارسال می‌کنیم که در آن CREDENTIAL یا رمز برنامه Firebase ما یا یک توکن احراز هویت است:

curl -X POST -d '{"Authenticated POST request"}' \
  'https://docs-examples.firebaseio.com/auth-example.json?auth=CREDENTIAL'

چاپ

پارامتر print به ما امکان می‌دهد قالب پاسخ خود را از پایگاه داده مشخص کنیم. اضافه کردن print=pretty به درخواست ما، داده‌ها را در قالبی قابل خواندن توسط انسان برمی‌گرداند. print=pretty توسط درخواست‌های GET ، PUT ، POST ، PATCH و DELETE پشتیبانی می‌شود.

برای جلوگیری از ارسال خروجی از سرور هنگام نوشتن داده‌ها، می‌توانیم print=silent را به درخواست خود اضافه کنیم. در صورت موفقیت‌آمیز بودن درخواست، پاسخ حاصل خالی خواهد بود و با کد وضعیت HTTP 204 No Content نشان داده می‌شود. print=silent توسط درخواست‌های GET ، PUT ، POST و PATCH پشتیبانی می‌شود.

نوشتن مقادیر سرور

مقادیر سرور را می‌توان در مکانی با استفاده از یک مقدار placeholder نوشت، که یک شیء با یک کلید ".sv" است. مقدار آن کلید، نوع مقدار سروری است که می‌خواهیم تنظیم کنیم. به عنوان مثال، برای تنظیم یک مهر زمانی هنگام ایجاد یک کاربر، می‌توانیم موارد زیر را انجام دهیم:

curl -X PUT -d '{".sv": "timestamp"}' \
  'https://docs-examples.firebaseio.com/alanisawesome/createdAt.json'

"timestamp" تنها مقدار پشتیبانی‌شده توسط سرور است و زمان سپری‌شده از عصر یونیکس را بر حسب میلی‌ثانیه نشان می‌دهد.

بهبود عملکرد نوشتن

اگر حجم زیادی از داده‌ها را در پایگاه داده می‌نویسیم، می‌توانیم از پارامتر print=silent برای بهبود عملکرد نوشتن و کاهش استفاده از پهنای باند استفاده کنیم. در حالت عادی نوشتن، سرور با داده‌های JSON که نوشته شده‌اند پاسخ می‌دهد. وقتی print=silent مشخص شود، سرور بلافاصله پس از دریافت داده‌ها اتصال را می‌بندد و استفاده از پهنای باند را کاهش می‌دهد.

در مواردی که درخواست‌های زیادی به پایگاه داده ارسال می‌کنیم، می‌توانیم با ارسال یک درخواست Keep-Alive در هدر HTTP، دوباره از اتصال HTTPS استفاده کنیم.

شرایط خطا

API REST تحت این شرایط کدهای خطا را برمی‌گرداند:

کدهای وضعیت HTTP
درخواست بد ۴۰۰

یکی از شرایط خطای زیر:

  • قادر به تجزیه داده‌های PUT یا POST نیست.
  • داده‌های PUT یا POST وجود ندارد.
  • درخواست سعی در PUT یا POST داده‌هایی دارد که بسیار بزرگ هستند.
  • فراخوانی REST API شامل نام‌های فرزند نامعتبر به عنوان بخشی از مسیر است.
  • مسیر فراخوانی REST API خیلی طولانی است.
  • درخواست شامل یک مقدار ناشناخته از سمت سرور است.
  • شاخص مربوط به پرس و جو در Firebase Realtime Database Security Rules شما تعریف نشده است.
  • درخواست از یکی از پارامترهای پرس و جو که مشخص شده است پشتیبانی نمی‌کند.
  • این درخواست، پارامترهای پرس‌وجو را با یک درخواست GET سطحی ترکیب می‌کند.
۴۰۱ غیرمجاز

یکی از شرایط خطای زیر:

۴۰۴ یافت نشد پایگاه داده Firebase مشخص شده یافت نشد.
خطای داخلی سرور ۵۰۰ سرور خطایی را برگرداند. برای جزئیات بیشتر به پیام خطا مراجعه کنید.
سرویس ۵۰۳ در دسترس نیست پایگاه داده Firebase Realtime مشخص شده موقتاً در دسترس نیست، به این معنی که درخواستی ارسال نشده است.

ایمن‌سازی داده‌ها

فایربیس یک زبان امنیتی دارد که به ما امکان می‌دهد تعریف کنیم کدام کاربران به گره‌های مختلف داده‌های ما دسترسی خواندن و نوشتن دارند. می‌توانید اطلاعات بیشتر در مورد آن را در Realtime Database Security Rules بخوانید.

حالا که ذخیره داده‌ها را پوشش دادیم، می‌توانیم در بخش بعدی یاد بگیریم که چگونه داده‌های خود را از پایگاه داده Firebase از طریق REST API بازیابی کنیم.