IndexedDB এর সাথে কাজ করুন, IndexedDB এর সাথে কাজ করুন

এই নির্দেশিকাটি IndexedDB API- এর মূল বিষয়গুলি কভার করে। আমরা Jake Archibald-এর IndexedDB প্রতিশ্রুত লাইব্রেরি ব্যবহার করছি, যা IndexedDB API-এর মতোই, কিন্তু প্রতিশ্রুতি ব্যবহার করে, যা আপনি আরও সংক্ষিপ্ত বাক্য গঠনের জন্য await করতে পারেন। এটি এর গঠন বজায় রাখার সময় এপিআইকে সরল করে।

IndexedDB হল একটি বৃহৎ মাপের, NoSQL স্টোরেজ সিস্টেম যা ব্যবহারকারীর ব্রাউজারে প্রায় যেকোনো কিছুর সঞ্চয়স্থানের অনুমতি দেয়। সাধারণ অনুসন্ধান, পান এবং পুট অ্যাকশন ছাড়াও, IndexedDB লেনদেন সমর্থন করে এবং এটি প্রচুর পরিমাণে কাঠামোগত ডেটা সংরক্ষণের জন্য উপযুক্ত।

প্রতিটি IndexedDB ডাটাবেস একটি মূলের জন্য অনন্য (সাধারণত সাইট ডোমেন বা সাবডোমেন), যার অর্থ এটি অন্য কোনো উত্স দ্বারা অ্যাক্সেস বা অ্যাক্সেস করা যায় না। এর ডেটা স্টোরেজ সীমা সাধারণত বড় হয়, যদি সেগুলি একেবারেই থাকে তবে বিভিন্ন ব্রাউজার সীমা এবং ডেটা উচ্ছেদকে ভিন্নভাবে পরিচালনা করে। আরও তথ্যের জন্য আরও পড়ার বিভাগটি দেখুন।

IndexedDB শর্তাবলী

ডাটাবেস
IndexedDB এর সর্বোচ্চ স্তর। এটিতে অবজেক্ট স্টোর রয়েছে, যার ফলে আপনি যে ডেটা বজায় রাখতে চান তা ধারণ করে। আপনি যে নামগুলি বেছে নিন তা দিয়ে আপনি একাধিক ডাটাবেস তৈরি করতে পারেন।
বস্তুর দোকান
ডেটা সঞ্চয় করার জন্য একটি পৃথক বালতি, রিলেশনাল ডাটাবেসের টেবিলের মতো। সাধারণত, আপনি যে ডেটা সঞ্চয় করছেন তার প্রতিটি প্রকারের (জাভাস্ক্রিপ্ট ডেটা টাইপ নয়) জন্য একটি অবজেক্ট স্টোর রয়েছে। ডাটাবেস টেবিলের বিপরীতে, একটি স্টোরের জাভাস্ক্রিপ্ট ডেটা প্রকারের ডেটা সামঞ্জস্যপূর্ণ হতে হবে না। উদাহরণ স্বরূপ, যদি একটি অ্যাপে তিনজন ব্যক্তির তথ্য সম্বলিত একটি people অবজেক্ট স্টোর থাকে, তাহলে সেই লোকেদের বয়সের বৈশিষ্ট্য হতে পারে 53 , 'twenty-five' , এবং unknown
সূচক
ডেটার একটি পৃথক সম্পত্তি দ্বারা অন্য অবজেক্ট স্টোর (যাকে রেফারেন্স অবজেক্ট স্টোর বলা হয়) ডেটা সংগঠিত করার জন্য এক ধরণের অবজেক্ট স্টোর। সূচকটি এই সম্পত্তি দ্বারা বস্তুর দোকানে রেকর্ড পুনরুদ্ধার করতে ব্যবহৃত হয়। উদাহরণস্বরূপ, আপনি যদি লোকেদের সঞ্চয় করে থাকেন তবে আপনি তাদের নাম, বয়স বা প্রিয় প্রাণী দ্বারা পরে তাদের আনতে চাইতে পারেন।
অপারেশন
ডাটাবেসের সাথে একটি মিথস্ক্রিয়া।
লেনদেন
একটি অপারেশন বা অপারেশন গ্রুপের চারপাশে একটি মোড়ক যা ডাটাবেসের অখণ্ডতা নিশ্চিত করে। যদি একটি লেনদেনের কোনো একটি ক্রিয়া ব্যর্থ হয়, তবে সেগুলির কোনোটিই প্রয়োগ করা হয় না এবং ডাটাবেসটি লেনদেন শুরুর আগে যে অবস্থায় ছিল সেখানে ফিরে আসে। IndexedDB-এ সমস্ত রিড বা রাইট অপারেশন অবশ্যই একটি লেনদেনের অংশ হতে হবে। এটি একই সময়ে ডাটাবেসে কাজ করা অন্যান্য থ্রেডগুলির সাথে দ্বন্দ্বের ঝুঁকি ছাড়াই পারমাণবিক পঠন-সংশোধন-রাইট অপারেশনের অনুমতি দেয়।
কার্সার
একটি ডাটাবেসে একাধিক রেকর্ডের উপর পুনরাবৃত্তি করার জন্য একটি প্রক্রিয়া।

IndexedDB সমর্থনের জন্য কিভাবে পরীক্ষা করবেন

IndexedDB প্রায় সর্বজনীনভাবে সমর্থিত । যাইহোক, আপনি যদি পুরানো ব্রাউজারগুলির সাথে কাজ করেন তবে শুধুমাত্র ক্ষেত্রে বৈশিষ্ট্য সনাক্তকরণ সমর্থন করা খারাপ ধারণা নয়। সবচেয়ে সহজ উপায় হল window অবজেক্ট চেক করা:

function indexedDBStuff () {
  // Check for IndexedDB support:
  if (!('indexedDB' in window)) {
    // Can't use IndexedDB
    console.log("This browser doesn't support IndexedDB");
    return;
  } else {
    // Do IndexedDB stuff here:
    // ...
  }
}

// Run IndexedDB code:
indexedDBStuff();

কিভাবে একটি ডাটাবেস খুলতে হয়

IndexedDB-এর সাহায্যে, আপনি যে কোনো নাম বেছে নিয়ে একাধিক ডাটাবেস তৈরি করতে পারেন। আপনি এটি খোলার চেষ্টা করার সময় একটি ডাটাবেস বিদ্যমান না থাকলে, এটি স্বয়ংক্রিয়ভাবে তৈরি হয়। একটি ডাটাবেস খুলতে, idb লাইব্রেরি থেকে openDB() পদ্ধতি ব্যবহার করুন:

import {openDB} from 'idb';

async function useDB () {
  // Returns a promise, which makes `idb` usable with async-await.
  const dbPromise = await openDB('example-database', version, events);
}

useDB();

এই পদ্ধতিটি একটি প্রতিশ্রুতি প্রদান করে যা একটি ডাটাবেস অবজেক্টের সমাধান করে। openDB() পদ্ধতি ব্যবহার করার সময়, ডাটাবেস সেট আপ করতে একটি নাম, সংস্করণ নম্বর এবং একটি ইভেন্ট অবজেক্ট প্রদান করুন।

এখানে প্রেক্ষাপটে openDB() পদ্ধতির একটি উদাহরণ রয়েছে:

import {openDB} from 'idb';

async function useDB () {
  // Opens the first version of the 'test-db1' database.
  // If the database does not exist, it will be created.
  const dbPromise = await openDB('test-db1', 1);
}

useDB();

বেনামী ফাংশনের শীর্ষে IndexedDB সমর্থনের জন্য চেক রাখুন। ব্রাউজার IndexedDB সমর্থন না করলে এটি ফাংশন থেকে প্রস্থান করে। যদি ফাংশনটি চালিয়ে যেতে পারে, এটি 'test-db1' নামে একটি ডাটাবেস খুলতে openDB() পদ্ধতিতে কল করে। এই উদাহরণে, ঐচ্ছিক ইভেন্ট অবজেক্টটি জিনিসগুলিকে সহজ রাখার জন্য বাদ দেওয়া হয়েছে, তবে আপনাকে IndexedDB এর সাথে কোনও অর্থপূর্ণ কাজ করতে এটি নির্দিষ্ট করতে হবে।

অবজেক্ট স্টোরের সাথে কীভাবে কাজ করবেন

একটি IndexedDB ডাটাবেসে এক বা একাধিক অবজেক্ট স্টোর থাকে, যার প্রত্যেকটিতে একটি কী-এর জন্য একটি কলাম থাকে এবং সেই কী-এর সাথে যুক্ত ডেটার জন্য আরেকটি কলাম থাকে।

অবজেক্ট স্টোর তৈরি করুন

একটি সুগঠিত IndexedDB ডাটাবেসের প্রতিটি ধরনের ডেটার জন্য একটি অবজেক্ট স্টোর থাকা উচিত যা স্থির থাকতে হবে। উদাহরণস্বরূপ, একটি সাইট যা ব্যবহারকারীর প্রোফাইল এবং নোটগুলি স্থির থাকে সেখানে person অবজেক্ট ধারণকারী একটি people অবজেক্ট স্টোর এবং notes অবজেক্ট ধারণকারী একটি note অবজেক্ট স্টোর থাকতে পারে।

ডাটাবেসের অখণ্ডতা নিশ্চিত করার জন্য, আপনি শুধুমাত্র একটি openDB() কলে ইভেন্ট অবজেক্টে অবজেক্ট স্টোর তৈরি বা সরাতে পারেন। ইভেন্ট অবজেক্ট একটি upgrade() পদ্ধতি প্রকাশ করে যা আপনাকে অবজেক্ট স্টোর তৈরি করতে দেয়। অবজেক্ট স্টোর তৈরি করতে upgrade() পদ্ধতির ভিতরে createObjectStore() পদ্ধতিতে কল করুন:

import {openDB} from 'idb';

async function createStoreInDB () {
  const dbPromise = await openDB('example-database', 1, {
    upgrade (db) {
      // Creates an object store:
      db.createObjectStore('storeName', options);
    }
  });
}

createStoreInDB();

এই পদ্ধতিটি অবজেক্ট স্টোরের নাম এবং একটি ঐচ্ছিক কনফিগারেশন অবজেক্ট নেয় যা আপনাকে অবজেক্ট স্টোরের জন্য বিভিন্ন বৈশিষ্ট্য নির্ধারণ করতে দেয়।

createObjectStore() কিভাবে ব্যবহার করবেন তার একটি উদাহরণ নিচে দেওয়া হল:

import {openDB} from 'idb';

async function createStoreInDB () {
  const dbPromise = await openDB('test-db1', 1, {
    upgrade (db) {
      console.log('Creating a new object store...');

      // Checks if the object store exists:
      if (!db.objectStoreNames.contains('people')) {
        // If the object store does not exist, create it:
        db.createObjectStore('people');
      }
    }
  });
}

createStoreInDB();

এই উদাহরণে, একটি ইভেন্ট অবজেক্ট অবজেক্ট স্টোর তৈরি করার জন্য openDB() পদ্ধতিতে পাস করা হয় এবং আগের মতই, ইভেন্ট অবজেক্টের upgrade() পদ্ধতিতে অবজেক্ট স্টোর তৈরির কাজ করা হয়। যাইহোক, যেহেতু আপনি ইতিমধ্যে বিদ্যমান একটি অবজেক্ট স্টোর তৈরি করার চেষ্টা করলে ব্রাউজার একটি ত্রুটি ছুঁড়ে দেয়, তাই আমরা একটি if স্টেটমেন্টে createObjectStore() পদ্ধতিটি মোড়ানোর পরামর্শ দিই যা অবজেক্ট স্টোরটি বিদ্যমান কিনা তা পরীক্ষা করে। if ব্লকের ভিতরে, 'firstOS' নামে একটি অবজেক্ট স্টোর তৈরি করতে createObjectStore() কল করুন।

প্রাথমিক কীগুলি কীভাবে সংজ্ঞায়িত করবেন

আপনি যখন অবজেক্ট স্টোর সংজ্ঞায়িত করেন, তখন প্রাথমিক কী ব্যবহার করে স্টোরে ডেটা কীভাবে স্বতন্ত্রভাবে চিহ্নিত করা হয় তা আপনি নির্ধারণ করতে পারেন। আপনি একটি কী পাথ সংজ্ঞায়িত করে বা একটি কী জেনারেটর ব্যবহার করে একটি প্রাথমিক কী সংজ্ঞায়িত করতে পারেন।

একটি মূল পথ হল এমন একটি সম্পত্তি যা সর্বদা বিদ্যমান এবং একটি অনন্য মান রয়েছে। উদাহরণস্বরূপ, একটি people অবজেক্ট স্টোরের ক্ষেত্রে, আপনি মূল পথ হিসাবে ইমেল ঠিকানা বেছে নিতে পারেন:

import {openDB} from 'idb';

async function createStoreInDB () {
  const dbPromise = await openDB('test-db2', 1, {
    upgrade (db) {
      if (!db.objectStoreNames.contains('people')) {
        db.createObjectStore('people', { keyPath: 'email' });
      }
    }
  });
}

createStoreInDB();

এই উদাহরণটি 'people' নামে একটি বস্তুর দোকান তৈরি করে এবং keyPath বিকল্পে প্রাথমিক কী হিসাবে email সম্পত্তি নির্ধারণ করে।

আপনি একটি কী জেনারেটর যেমন autoIncrement ব্যবহার করতে পারেন। কী জেনারেটর বস্তুর দোকানে যোগ করা প্রতিটি বস্তুর জন্য একটি অনন্য মান তৈরি করে। ডিফল্টরূপে, আপনি একটি কী নির্দিষ্ট না করলে, IndexedDB একটি কী তৈরি করে এবং ডেটা থেকে আলাদাভাবে সংরক্ষণ করে।

নিম্নলিখিত উদাহরণটি 'notes' নামে একটি অবজেক্ট স্টোর তৈরি করে এবং একটি স্বয়ংক্রিয়-বর্ধিত সংখ্যা হিসাবে স্বয়ংক্রিয়ভাবে বরাদ্দ করা প্রাথমিক কী সেট করে:

import {openDB} from 'idb';

async function createStoreInDB () {
  const dbPromise = await openDB('test-db2', 1, {
    upgrade (db) {
      if (!db.objectStoreNames.contains('notes')) {
        db.createObjectStore('notes', { autoIncrement: true });
      }
    }
  });
}

createStoreInDB();

নিম্নলিখিত উদাহরণটি আগের উদাহরণের মতোই, কিন্তু এবার স্বয়ংক্রিয়ভাবে বৃদ্ধির মানটি 'id' নামের একটি সম্পত্তিতে স্পষ্টভাবে বরাদ্দ করা হয়েছে।

import {openDB} from 'idb';

async function createStoreInDB () {
  const dbPromise = await openDB('test-db2', 1, {
    upgrade (db) {
      if (!db.objectStoreNames.contains('logs')) {
        db.createObjectStore('logs', { keyPath: 'id', autoIncrement: true });
      }
    }
  });
}

createStoreInDB();

কী সংজ্ঞায়িত করার জন্য কোন পদ্ধতি ব্যবহার করা হবে তা আপনার ডেটার উপর নির্ভর করে। যদি আপনার ডেটাতে এমন একটি সম্পত্তি থাকে যা সর্বদা অনন্য থাকে, তাহলে আপনি এই স্বতন্ত্রতা প্রয়োগ করতে এটিকে keyPath বানাতে পারেন। অন্যথায়, একটি স্বয়ংক্রিয়-বর্ধিত মান ব্যবহার করুন।

নিম্নলিখিত কোড তিনটি অবজেক্ট স্টোর তৈরি করে যা অবজেক্ট স্টোরগুলিতে প্রাথমিক কীগুলি সংজ্ঞায়িত করার বিভিন্ন উপায় প্রদর্শন করে:

import {openDB} from 'idb';

async function createStoresInDB () {
  const dbPromise = await openDB('test-db2', 1, {
    upgrade (db) {
      if (!db.objectStoreNames.contains('people')) {
        db.createObjectStore('people', { keyPath: 'email' });
      }

      if (!db.objectStoreNames.contains('notes')) {
        db.createObjectStore('notes', { autoIncrement: true });
      }

      if (!db.objectStoreNames.contains('logs')) {
        db.createObjectStore('logs', { keyPath: 'id', autoIncrement: true });
      }
    }
  });
}

createStoresInDB();

কিভাবে সূচক সংজ্ঞায়িত করা যায়

সূচকগুলি হল এক ধরণের অবজেক্ট স্টোর যা একটি নির্দিষ্ট সম্পত্তি দ্বারা রেফারেন্স অবজেক্ট স্টোর থেকে ডেটা পুনরুদ্ধার করতে ব্যবহৃত হয়। একটি সূচী রেফারেন্স অবজেক্ট স্টোরের ভিতরে থাকে এবং একই ডেটা ধারণ করে, তবে রেফারেন্স স্টোরের প্রাথমিক কী এর পরিবর্তে এর মূল পথ হিসাবে নির্দিষ্ট সম্পত্তি ব্যবহার করে। আপনি যখন আপনার অবজেক্ট স্টোর তৈরি করেন তখন সূচীগুলি অবশ্যই তৈরি করা উচিত এবং আপনার ডেটাতে একটি অনন্য সীমাবদ্ধতা নির্ধারণ করতে ব্যবহার করা যেতে পারে।

একটি সূচক তৈরি করতে, একটি অবজেক্ট স্টোর উদাহরণে createIndex() পদ্ধতিতে কল করুন:

import {openDB} from 'idb';

async function createIndexInStore() {
  const dbPromise = await openDB('storeName', 1, {
    upgrade (db) {
      const objectStore = db.createObjectStore('storeName');

      objectStore.createIndex('indexName', 'property', options);
    }
  });
}

createIndexInStore();

এই পদ্ধতিটি একটি সূচক বস্তু তৈরি করে এবং ফেরত দেয়। অবজেক্ট স্টোরের উদাহরণে createIndex() পদ্ধতিটি প্রথম আর্গুমেন্ট হিসাবে নতুন সূচকের নাম নেয় এবং দ্বিতীয় আর্গুমেন্টটি আপনি যে ডেটা সূচী করতে চান তার সম্পত্তিকে নির্দেশ করে। চূড়ান্ত যুক্তি আপনাকে দুটি বিকল্প নির্ধারণ করতে দেয় যা সূচকটি কীভাবে কাজ করে তা নির্ধারণ করে: unique এবং multiEntryunique true সেট করা থাকলে, সূচকটি একটি একক কী-এর জন্য সদৃশ মান অনুমোদন করে না। এরপরে, multiEntry নির্ধারণ করে কিভাবে createIndex() আচরণ করে যখন ইন্ডেক্স করা প্রপার্টি একটি অ্যারে হয়। যদি এটি true তে সেট করা হয়, createIndex() প্রতিটি অ্যারের উপাদানের জন্য সূচকে একটি এন্ট্রি যোগ করে। অন্যথায়, এটি অ্যারে ধারণকারী একটি একক এন্ট্রি যোগ করে।

এখানে একটি উদাহরণ:

import {openDB} from 'idb';

async function createIndexesInStores () {
  const dbPromise = await openDB('test-db3', 1, {
    upgrade (db) {
      if (!db.objectStoreNames.contains('people')) {
        const peopleObjectStore = db.createObjectStore('people', { keyPath: 'email' });

        peopleObjectStore.createIndex('gender', 'gender', { unique: false });
        peopleObjectStore.createIndex('ssn', 'ssn', { unique: true });
      }

      if (!db.objectStoreNames.contains('notes')) {
        const notesObjectStore = db.createObjectStore('notes', { autoIncrement: true });

        notesObjectStore.createIndex('title', 'title', { unique: false });
      }

      if (!db.objectStoreNames.contains('logs')) {
        const logsObjectStore = db.createObjectStore('logs', { keyPath: 'id', autoIncrement: true });
      }
    }
  });
}

createIndexesInStores();

এই উদাহরণে, 'people' এবং 'notes' অবজেক্ট স্টোরের সূচী রয়েছে। ইনডেক্স তৈরি করতে, প্রথমে createObjectStore() (একটি অবজেক্ট স্টোর অবজেক্ট) এর ফলাফল একটি ভেরিয়েবলে বরাদ্দ করুন যাতে আপনি এটিতে createIndex() কল করতে পারেন।

কিভাবে ডেটা নিয়ে কাজ করবেন

এই বিভাগে কীভাবে ডেটা তৈরি, পড়তে, আপডেট করতে এবং মুছতে হয় তা বর্ণনা করে। এই অপারেশনগুলি সমস্ত অ্যাসিঙ্ক্রোনাস, প্রতিশ্রুতি ব্যবহার করে যেখানে IndexedDB API অনুরোধগুলি ব্যবহার করে। এটি এপিআইকে সরল করে। অনুরোধ দ্বারা ট্রিগার হওয়া ইভেন্টগুলি শোনার পরিবর্তে, আপনি ডাটাবেসের সাথে ইন্টারঅ্যাকশন শুরু করতে openDB() পদ্ধতি থেকে ফিরে আসা ডাটাবেস অবজেক্টে .then() কল করতে পারেন, বা এটি তৈরির await

IndexedDB-তে সমস্ত ডেটা অপারেশন একটি লেনদেনের মধ্যে সঞ্চালিত হয়। প্রতিটি অপারেশন নিম্নলিখিত ফর্ম আছে:

  1. ডাটাবেস অবজেক্ট পান।
  2. ডাটাবেসে লেনদেন খুলুন।
  3. লেনদেনে অবজেক্ট স্টোর খুলুন।
  4. বস্তুর দোকানে অপারেশন সঞ্চালন.

একটি লেনদেন একটি অপারেশন বা অপারেশন গ্রুপের চারপাশে একটি নিরাপদ মোড়ক হিসাবে চিন্তা করা যেতে পারে। যদি একটি লেনদেনের মধ্যে একটি ক্রিয়া ব্যর্থ হয়, তবে সমস্ত ক্রিয়াগুলি ফিরিয়ে দেওয়া হয়। লেনদেনগুলি এক বা একাধিক বস্তুর দোকানের জন্য নির্দিষ্ট, যা আপনি লেনদেন খোলার সময় সংজ্ঞায়িত করেন। এগুলি কেবল পঠনযোগ্য বা পড়তে এবং লিখতে পারে। এটি বোঝায় যে লেনদেনের ভিতরে ক্রিয়াকলাপগুলি ডেটা পড়ে বা ডাটাবেসে পরিবর্তন করে কিনা।

ডেটা তৈরি করুন

ডেটা তৈরি করতে, ডাটাবেস ইনস্ট্যান্সে add() পদ্ধতিতে কল করুন এবং আপনি যে ডেটা যোগ করতে চান তা পাস করুন। add() পদ্ধতির প্রথম আর্গুমেন্ট হল অবজেক্ট স্টোর যেখানে আপনি ডেটা যোগ করতে চান এবং দ্বিতীয় আর্গুমেন্ট হল একটি অবজেক্ট যাতে আপনি যে ক্ষেত্রগুলি এবং সংশ্লিষ্ট ডেটা যোগ করতে চান। এখানে সবচেয়ে সহজ উদাহরণ, যেখানে ডেটার একটি একক সারি যোগ করা হয়েছে:

import {openDB} from 'idb';

async function addItemToStore () {
  const db = await openDB('example-database', 1);

  await db.add('storeName', {
    field: 'data'
  });
}

addItemToStore();

প্রতিটি add() কল একটি লেনদেনের মধ্যে ঘটে, তাই প্রতিশ্রুতিটি সফলভাবে সমাধান করা হলেও, এর অর্থ এই নয় যে অপারেশনটি কাজ করেছে। অ্যাড অপারেশন করা হয়েছে তা নিশ্চিত করতে, আপনাকে পুরো লেনদেন transaction.done() পদ্ধতি ব্যবহার করে সম্পন্ন হয়েছে কিনা তা পরীক্ষা করতে হবে। এটি একটি প্রতিশ্রুতি যা লেনদেন সম্পূর্ণ হলে সমাধান করে এবং লেনদেনে ত্রুটি হলে প্রত্যাখ্যান করে। সমস্ত "লেখা" অপারেশনের জন্য আপনাকে অবশ্যই এই চেকটি সম্পাদন করতে হবে, কারণ ডাটাবেসের পরিবর্তনগুলি আসলে ঘটেছে তা জানার এটিই একমাত্র উপায়।

নিম্নলিখিত কোড একটি লেনদেনের ভিতরে add() পদ্ধতির ব্যবহার দেখায়:

import {openDB} from 'idb';

async function addItemsToStore () {
  const db = await openDB('test-db4', 1, {
    upgrade (db) {
      if (!db.objectStoreNames.contains('foods')) {
        db.createObjectStore('foods', { keyPath: 'name' });
      }
    }
  });
  
  // Create a transaction on the 'foods' store in read/write mode:
  const tx = db.transaction('foods', 'readwrite');

  // Add multiple items to the 'foods' store in a single transaction:
  await Promise.all([
    tx.store.add({
      name: 'Sandwich',
      price: 4.99,
      description: 'A very tasty sandwich!',
      created: new Date().getTime(),
    }),
    tx.store.add({
      name: 'Eggs',
      price: 2.99,
      description: 'Some nice eggs you can cook up!',
      created: new Date().getTime(),
    }),
    tx.done
  ]);
}

addItemsToStore();

একবার আপনি ডাটাবেস খুললে (এবং প্রয়োজনে একটি অবজেক্ট স্টোর তৈরি করুন), আপনাকে transaction() পদ্ধতিতে কল করে একটি লেনদেন খুলতে হবে। এই পদ্ধতিতে আপনি যে দোকানে লেনদেন করতে চান তার জন্য একটি যুক্তি, সেইসাথে মোড লাগে। এই ক্ষেত্রে, আমরা দোকানে লিখতে আগ্রহী, তাই এই উদাহরণটি 'readwrite' নির্দিষ্ট করে।

পরবর্তী ধাপ হল লেনদেনের অংশ হিসেবে দোকানে আইটেম যোগ করা শুরু করা। পূর্ববর্তী উদাহরণে, আমরা 'foods' দোকানে তিনটি অপারেশন নিয়ে কাজ করছি যার প্রত্যেকটি একটি প্রতিশ্রুতি প্রদান করে:

  1. একটি সুস্বাদু স্যান্ডউইচ জন্য একটি রেকর্ড যোগ করা.
  2. কিছু ডিমের জন্য একটি রেকর্ড যোগ করা হচ্ছে।
  3. লেনদেন সম্পূর্ণ হওয়ার সংকেত ( tx.done )।

যেহেতু এই সমস্ত ক্রিয়াগুলি সমস্তই প্রতিশ্রুতি-ভিত্তিক, সেগুলি শেষ হওয়ার জন্য আমাদের অপেক্ষা করতে হবে। Promise.all এর কাছে এই প্রতিশ্রুতিগুলি পাস করা এটি সম্পন্ন করার একটি চমৎকার, এর্গোনমিক উপায়। Promise.all প্রতিশ্রুতির একটি অ্যারে গ্রহণ করে এবং যখন এটিকে দেওয়া সমস্ত প্রতিশ্রুতি মীমাংসা হয়ে যায় তখন শেষ হয়।

দুটি রেকর্ড যোগ করার জন্য, লেনদেনের উদাহরণের store ইন্টারফেস কল add() এবং এতে ডেটা পাস করে। আপনি Promise.all কলের await করতে পারেন যাতে লেনদেন শেষ হলে এটি শেষ হয়।

ডেটা পড়ুন

ডেটা পড়ার জন্য, আপনি openDB() পদ্ধতি ব্যবহার করে পুনরুদ্ধার করা ডাটাবেসের উদাহরণে get() পদ্ধতিতে কল করুন। get() স্টোরের নাম এবং আপনি যে বস্তুটি পুনরুদ্ধার করতে চান তার প্রাথমিক কী মান নেয়। এখানে একটি মৌলিক উদাহরণ:

import {openDB} from 'idb';

async function getItemFromStore () {
  const db = await openDB('example-database', 1);

  // Get a value from the object store by its primary key value:
  const value = await db.get('storeName', 'unique-primary-key-value');
}

getItemFromStore();

add() এর মত, get() পদ্ধতিটি একটি প্রতিশ্রুতি প্রদান করে, তাই আপনি যদি পছন্দ করেন তবে আপনি এটির await করতে পারেন বা প্রতিশ্রুতির .then() কলব্যাক ব্যবহার করতে পারেন।

নিম্নলিখিত উদাহরণটি 'test-db4' ডাটাবেসের 'foods' অবজেক্ট স্টোরে get() পদ্ধতি ব্যবহার করে 'name' প্রাথমিক কী দ্বারা একটি একক সারি পেতে:

import {openDB} from 'idb';

async function getItemFromStore () {
  const db = await openDB('test-db4', 1);
  const value = await db.get('foods', 'Sandwich');

  console.dir(value);
}

getItemFromStore();

ডাটাবেস থেকে একটি একক সারি পুনরুদ্ধার করা মোটামুটি সহজ: ডাটাবেসটি খুলুন এবং যে সারি থেকে আপনি ডেটা পেতে চান তার অবজেক্ট স্টোর এবং প্রাথমিক কী মান নির্দিষ্ট করুন। যেহেতু get() পদ্ধতি একটি প্রতিশ্রুতি প্রদান করে, আপনি এটির await করতে পারেন।

ডেটা আপডেট করুন

ডেটা আপডেট করতে, অবজেক্ট স্টোরে put() পদ্ধতিতে কল করুন। put() পদ্ধতিটি add() পদ্ধতির অনুরূপ এবং ডেটা তৈরি করতে add() এর জায়গায় ব্যবহার করা যেতে পারে। এখানে একটি প্রাথমিক কী মান দ্বারা একটি অবজেক্ট স্টোরে একটি সারি আপডেট করতে put() ব্যবহার করার একটি প্রাথমিক উদাহরণ রয়েছে:

import {openDB} from 'idb';

async function updateItemInStore () {
  const db = await openDB('example-database', 1);

  // Update a value from in an object store with an inline key:
  await db.put('storeName', { inlineKeyName: 'newValue' });

  // Update a value from in an object store with an out-of-line key.
  // In this case, the out-of-line key value is 1, which is the
  // auto-incremented value.
  await db.put('otherStoreName', { field: 'value' }, 1);
}

updateItemInStore();

অন্যান্য পদ্ধতির মতো, এই পদ্ধতিটি একটি প্রতিশ্রুতি প্রদান করে। আপনি একটি লেনদেনের অংশ হিসাবে put() ব্যবহার করতে পারেন। এখানে আগে থেকে 'foods' স্টোর ব্যবহার করে একটি উদাহরণ দেওয়া হল যা স্যান্ডউইচ এবং ডিমের দাম আপডেট করে:

import {openDB} from 'idb';

async function updateItemsInStore () {
  const db = await openDB('test-db4', 1);
  
  // Create a transaction on the 'foods' store in read/write mode:
  const tx = db.transaction('foods', 'readwrite');

  // Update multiple items in the 'foods' store in a single transaction:
  await Promise.all([
    tx.store.put({
      name: 'Sandwich',
      price: 5.99,
      description: 'A MORE tasty sandwich!',
      updated: new Date().getTime() // This creates a new field
    }),
    tx.store.put({
      name: 'Eggs',
      price: 3.99,
      description: 'Some even NICER eggs you can cook up!',
      updated: new Date().getTime() // This creates a new field
    }),
    tx.done
  ]);
}

updateItemsInStore();

আইটেমগুলি কীভাবে আপডেট করা হয় তা নির্ভর করে আপনি কীভাবে একটি কী সেট করেন তার উপর। আপনি যদি একটি keyPath সেট করেন, অবজেক্ট স্টোরের প্রতিটি সারি একটি ইনলাইন কী এর সাথে যুক্ত থাকে। পূর্ববর্তী উদাহরণটি এই কীটির উপর ভিত্তি করে সারিগুলি আপডেট করে এবং যখন আপনি এই পরিস্থিতিতে সারিগুলি আপডেট করেন, তখন অবজেক্ট স্টোরে উপযুক্ত আইটেম আপডেট করার জন্য আপনাকে সেই কীটি নির্দিষ্ট করতে হবে। আপনি প্রাথমিক কী হিসাবে একটি autoIncrement সেট করে একটি আউট-অফ-লাইন কী তৈরি করতে পারেন।

ডেটা মুছুন

ডেটা মুছে ফেলার জন্য, অবজেক্ট স্টোরে delete() পদ্ধতিতে কল করুন:

import {openDB} from 'idb';

async function deleteItemFromStore () {
  const db = await openDB('example-database', 1);

  // Delete a value 
  await db.delete('storeName', 'primary-key-value');
}

deleteItemFromStore();

যেমন add() এবং put() , আপনি এটি একটি লেনদেনের অংশ হিসাবে ব্যবহার করতে পারেন:

import {openDB} from 'idb';

async function deleteItemsFromStore () {
  const db = await openDB('test-db4', 1);
  
  // Create a transaction on the 'foods' store in read/write mode:
  const tx = db.transaction('foods', 'readwrite');

  // Delete multiple items from the 'foods' store in a single transaction:
  await Promise.all([
    tx.store.delete('Sandwich'),
    tx.store.delete('Eggs'),
    tx.done
  ]);
}

deleteItemsFromStore();

ডাটাবেস ইন্টারঅ্যাকশনের গঠন অন্যান্য ক্রিয়াকলাপের মতোই। আপনি Promise.all এ পাস করা অ্যারেতে tx.done পদ্ধতিটি অন্তর্ভুক্ত করে পুরো লেনদেন সম্পন্ন হয়েছে কিনা তা পরীক্ষা করতে ভুলবেন না।

সব তথ্য পাওয়া যাচ্ছে

এখন পর্যন্ত আপনি একবারে স্টোর থেকে শুধুমাত্র একটি বস্তু পুনরুদ্ধার করেছেন। আপনি getAll() পদ্ধতি বা কার্সার ব্যবহার করে অবজেক্ট স্টোর বা সূচী থেকে সমস্ত ডেটা বা উপসেট পুনরুদ্ধার করতে পারেন।

getAll() পদ্ধতি

একটি অবজেক্ট স্টোরের সমস্ত ডেটা পুনরুদ্ধার করার সবচেয়ে সহজ উপায় হল অবজেক্ট স্টোর বা সূচকে getAll() কল করা, যেমন:

import {openDB} from 'idb';

async function getAllItemsFromStore () {
  const db = await openDB('test-db4', 1);

  // Get all values from the designated object store:
  const allValues = await db.getAll('storeName');

  console.dir(allValues);
}

getAllItemsFromStore();

এই পদ্ধতিটি অবজেক্ট স্টোরের সমস্ত বস্তু ফেরত দেয়, কোনো বাধা ছাড়াই। এটি একটি অবজেক্ট স্টোর থেকে সমস্ত মান পাওয়ার সবচেয়ে সরাসরি উপায়, তবে সর্বনিম্ন নমনীয়ও।

import {openDB} from 'idb';

async function getAllItemsFromStore () {
  const db = await openDB('test-db4', 1);

  // Get all values from the designated object store:
  const allValues = await db.getAll('foods');

  console.dir(allValues);
}

getAllItemsFromStore();

এই উদাহরণটি 'foods' বস্তুর দোকানে getAll() কল করে। এটি প্রাথমিক কী দ্বারা আদেশকৃত 'foods' থেকে সমস্ত বস্তু ফেরত দেয়।

কিভাবে কার্সার ব্যবহার করবেন

একাধিক বস্তু পুনরুদ্ধার করার জন্য কার্সারগুলি আরও নমনীয় উপায়। একটি কার্সার একটি অবজেক্ট স্টোরের প্রতিটি বস্তুকে নির্বাচন করে বা একে একে সূচী করে, যখন এটি নির্বাচন করা হয় তখন আপনাকে ডেটার সাথে কিছু করতে দেয়। কার্সার, অন্যান্য ডাটাবেস অপারেশনের মত, লেনদেনে কাজ করে।

একটি কার্সার তৈরি করতে, লেনদেনের অংশ হিসাবে অবজেক্ট স্টোরে openCursor() কল করুন। পূর্ববর্তী উদাহরণগুলি থেকে 'foods' স্টোর ব্যবহার করে, একটি বস্তুর দোকানে ডেটার সমস্ত সারির মাধ্যমে একটি কার্সারকে কীভাবে অগ্রসর করা যায়:

import {openDB} from 'idb';

async function getAllItemsFromStoreWithCursor () {
  const db = await openDB('test-db4', 1);
  const tx = await db.transaction('foods', 'readonly');

  // Open a cursor on the designated object store:
  let cursor = await tx.store.openCursor();

  // Iterate on the cursor, row by row:
  while (cursor) {
    // Show the data in the row at the current cursor position:
    console.log(cursor.key, cursor.value);

    // Advance the cursor to the next row:
    cursor = await cursor.continue();
  }
}

getAllItemsFromStoreWithCursor();

এই ক্ষেত্রে লেনদেন 'readonly' মোডে খোলা হয়, এবং এর openCursor পদ্ধতি বলা হয়। পরবর্তী while লুপে, কার্সারের বর্তমান অবস্থানে থাকা সারিটির key এবং value বৈশিষ্ট্যগুলি পড়তে পারে এবং আপনি সেই মানগুলিকে আপনার অ্যাপের জন্য সবচেয়ে অর্থবহ যেভাবেই পরিচালনা করতে পারেন৷ আপনি প্রস্তুত হলে, পরবর্তী সারিতে যাওয়ার জন্য আপনি cursor অবজেক্টের continue() পদ্ধতিতে কল করতে পারেন এবং যখন কার্সার ডেটাসেটের শেষ প্রান্তে পৌঁছে তখন while লুপটি বন্ধ হয়ে যায়।

রেঞ্জ এবং সূচী সহ কার্সার ব্যবহার করুন

সূচীগুলি আপনাকে প্রাথমিক কী ব্যতীত অন্য একটি বৈশিষ্ট্য দ্বারা একটি অবজেক্ট স্টোরে ডেটা আনতে দেয়। আপনি যেকোন প্রপার্টিতে একটি সূচী তৈরি করতে পারেন, যা সূচীর জন্য keyPath হয়ে ওঠে, সেই প্রপার্টির একটি রেঞ্জ নির্দিষ্ট করুন এবং getAll() বা একটি কার্সার ব্যবহার করে রেঞ্জের মধ্যে ডেটা পেতে পারেন।

IDBKeyRange অবজেক্ট ব্যবহার করে আপনার পরিসীমা নির্ধারণ করুন। এবং নিম্নলিখিত পদ্ধতিগুলির মধ্যে যেকোনো একটি:

upperBound() এবং lowerBound() পদ্ধতি রেঞ্জের উপরের এবং নিম্ন সীমা নির্দিষ্ট করে।

IDBKeyRange.lowerBound(indexKey);

বা:

IDBKeyRange.upperBound(indexKey);

তারা প্রত্যেকে একটি যুক্তি নেয়: আপনি যে আইটেমটিকে উপরের বা নিম্ন সীমা হিসাবে নির্দিষ্ট করতে চান তার জন্য সূচকের keyPath মান।

bound() পদ্ধতি একটি উপরের এবং নিম্ন সীমা উভয় নির্দিষ্ট করে:

IDBKeyRange.bound(lowerIndexKey, upperIndexKey);

এই ফাংশনগুলির জন্য পরিসর ডিফল্টরূপে অন্তর্ভুক্ত, যার মানে এটি পরিসীমার সীমা হিসাবে নির্দিষ্ট করা ডেটা অন্তর্ভুক্ত করে। এই মানগুলি বাদ দিতে, নিম্ন ও উপরের সীমার জন্য যথাক্রমে lowerBound() বা upperBound() এর জন্য দ্বিতীয় আর্গুমেন্ট বা bound() এর তৃতীয় এবং চতুর্থ আর্গুমেন্ট হিসাবে true পাস করে পরিসীমাটিকে একচেটিয়া হিসাবে নির্দিষ্ট করুন৷

পরবর্তী উদাহরণটি 'foods' বস্তুর দোকানে 'price' সম্পত্তির একটি সূচক ব্যবহার করে। দোকানে এখন সীমার উপরের এবং নিম্ন সীমার জন্য দুটি ইনপুট সহ একটি ফর্ম সংযুক্ত রয়েছে৷ এই সীমার মধ্যে দাম সহ খাবারগুলি খুঁজতে নিম্নলিখিত কোড ব্যবহার করুন:

import {openDB} from 'idb';

async function searchItems (lower, upper) {
  if (!lower === '' && upper === '') {
    return;
  }

  let range;

  if (lower !== '' && upper !== '') {
    range = IDBKeyRange.bound(lower, upper);
  } else if (lower === '') {
    range = IDBKeyRange.upperBound(upper);
  } else {
    range = IDBKeyRange.lowerBound(lower);
  }

  const db = await openDB('test-db4', 1);
  const tx = await db.transaction('foods', 'readonly');
  const index = tx.store.index('price');

  // Open a cursor on the designated object store:
  let cursor = await index.openCursor(range);

  if (!cursor) {
    return;
  }

  // Iterate on the cursor, row by row:
  while (cursor) {
    // Show the data in the row at the current cursor position:
    console.log(cursor.key, cursor.value);

    // Advance the cursor to the next row:
    cursor = await cursor.continue();
  }
}

// Get items priced between one and four dollars:
searchItems(1.00, 4.00);

উদাহরণ কোডটি প্রথমে সীমার মানগুলি পায় এবং সীমা বিদ্যমান কিনা তা পরীক্ষা করে। কোডের পরবর্তী ব্লক মানগুলির উপর ভিত্তি করে পরিসর সীমাবদ্ধ করতে কোন পদ্ধতি ব্যবহার করবে তা নির্ধারণ করে। ডাটাবেস ইন্টারঅ্যাকশনে, লেনদেনের উপর বস্তুর দোকানটি যথারীতি খুলুন, তারপর অবজেক্ট স্টোরে 'price' সূচক খুলুন। 'price' সূচক আপনাকে মূল্য অনুসারে আইটেমগুলি অনুসন্ধান করতে দেয়।

কোডটি তারপর সূচকে একটি কার্সার খোলে এবং পরিসরে চলে যায়। কার্সার একটি প্রতিশ্রুতি প্রদান করে যা রেঞ্জের মধ্যে প্রথম অবজেক্টের প্রতিনিধিত্ব করে, অথবা যদি রেঞ্জের মধ্যে কোন ডেটা না থাকে তবে undefinedcursor.continue() পদ্ধতিটি পরবর্তী অবজেক্টের প্রতিনিধিত্বকারী একটি কার্সার প্রদান করে এবং আপনি পরিসরের শেষে না পৌঁছা পর্যন্ত লুপের মাধ্যমে চলতে থাকে।

ডাটাবেস সংস্করণ

যখন আপনি openDB() পদ্ধতিতে কল করেন, আপনি দ্বিতীয় প্যারামিটারে ডাটাবেস সংস্করণ নম্বর নির্দিষ্ট করতে পারেন। এই গাইডের সমস্ত উদাহরণে, সংস্করণটি 1 তে সেট করা হয়েছে, তবে একটি ডাটাবেসকে একটি নতুন সংস্করণে আপগ্রেড করা যেতে পারে যদি আপনি এটিকে কোনোভাবে পরিবর্তন করতে চান। যদি নির্দিষ্ট করা সংস্করণটি বিদ্যমান ডাটাবেসের সংস্করণের চেয়ে বড় হয়, তাহলে ইভেন্ট অবজেক্টে upgrade কলব্যাক কার্যকর হয়, যা আপনাকে ডাটাবেসে নতুন অবজেক্ট স্টোর এবং ইনডেক্স যোগ করার অনুমতি দেয়।

upgrade কলব্যাকের db অবজেক্টের একটি বিশেষ oldVersion বৈশিষ্ট্য রয়েছে, যা ব্রাউজারটির অ্যাক্সেস থাকা ডাটাবেসের সংস্করণ নম্বর নির্দেশ করে। বিদ্যমান ডাটাবেস সংস্করণ নম্বরের উপর ভিত্তি করে upgrade কলব্যাকের ভিতরে কোডের ব্লকগুলি কার্যকর করতে আপনি এই সংস্করণ নম্বরটিকে একটি switch বিবৃতিতে পাস করতে পারেন৷ এখানে একটি উদাহরণ:

import {openDB} from 'idb';

const db = await openDB('example-database', 2, {
  upgrade (db, oldVersion) {
    switch (oldVersion) {
      case 0:
        // Create first object store:
        db.createObjectStore('store', { keyPath: 'name' });

      case 1:
        // Get the original object store, and create an index on it:
        const tx = await db.transaction('store', 'readwrite');
        tx.store.createIndex('name', 'name');
    }
  }
});

এই উদাহরণটি ডাটাবেসের নতুন সংস্করণটিকে 2 এ সেট করে। যখন এই কোডটি প্রথম কার্যকর হয়, তখন ব্রাউজারে ডাটাবেসটি বিদ্যমান থাকে না, তাই oldVersion হল 0 , এবং switch বিবৃতিটি case 0 থেকে শুরু হয়। উদাহরণে, এটি ডাটাবেসে একটি 'store' অবজেক্ট স্টোর যোগ করে।

মূল পয়েন্ট: switch স্টেটমেন্টে, সাধারণত প্রতিটি case ব্লকের পরে একটি break থাকে, তবে এটি ইচ্ছাকৃতভাবে এখানে ব্যবহার করা হয় না। এইভাবে, যদি বিদ্যমান ডাটাবেসটি কয়েকটি সংস্করণের পিছনে থাকে, বা যদি এটি বিদ্যমান না থাকে, কোডটি আপ টু ডেট না হওয়া পর্যন্ত বাকি case ব্লকগুলির মাধ্যমে চলতে থাকে। সুতরাং উদাহরণে, ব্রাউজারটি case 1 এর মাধ্যমে সঞ্চালন অব্যাহত রাখে, store অবজেক্ট স্টোরে একটি name সূচক তৈরি করে।

'store' অবজেক্ট স্টোরে একটি 'description' সূচী তৈরি করতে, সংস্করণ নম্বরটি আপডেট করুন এবং নিম্নরূপ একটি নতুন case ব্লক যোগ করুন:

import {openDB} from 'idb';

const db = await openDB('example-database', 3, {
  upgrade (db, oldVersion) {
    switch (oldVersion) {
      case 0:
        // Create first object store:
        db.createObjectStore('store', { keyPath: 'name' });

      case 1:
        // Get the original object store, and create an index on it:
        const tx = await db.transaction('store', 'readwrite');
        tx.store.createIndex('name', 'name');

      case 2:
        const tx = await db.transaction('store', 'readwrite');
        tx.store.createIndex('description', 'description');
    }
  }
});

পূর্ববর্তী উদাহরণে আপনার তৈরি করা ডাটাবেসটি যদি এখনও ব্রাউজারে বিদ্যমান থাকে, যখন এটি কার্যকর হয়, oldVersion 2 হয়। ব্রাউজার case 0 এবং case 1 এড়িয়ে যায় এবং case 2 এ কোডটি এক্সিকিউট করে, যা একটি description সূচক তৈরি করে। এর পরে, ব্রাউজারটির সংস্করণ 3-এ একটি ডাটাবেস রয়েছে যেখানে name এবং description সূচী সহ একটি store অবজেক্ট স্টোর রয়েছে।

আরও পড়া

নিম্নলিখিত সংস্থানগুলি IndexedDB ব্যবহারের জন্য আরও তথ্য এবং প্রসঙ্গ সরবরাহ করে।

IndexedDB ডকুমেন্টেশন

ডেটা স্টোরেজ সীমা