Utiliser IndexedDB

Ce guide aborde les principes de base API IndexedDB : Nous utilisons le modèle IndexedDB Promised , qui est très semblable à l'API IndexedDB, mais utilise des promesses, vous pouvez utiliser await pour obtenir une syntaxe plus concise. Cela simplifie l'API tout en maintenir sa structure.

Qu'est-ce que IndexedDB ?

IndexedDB est un système de stockage NoSQL à grande échelle qui permet de stocker sur tout ce qui se passe dans le navigateur de l'utilisateur. En plus des opérations de recherche habituelles, les actions "put", "IndexedDB" accepte aussi les transactions, et il est parfaitement adapté de grandes quantités de données structurées.

Chaque base de données IndexedDB est associée à une origine unique. (généralement le domaine ou le sous-domaine du site), ce qui signifie qu'il est impossible d'y accéder ou d'une autre origine. Ses limites de stockage des données sont généralement volumineux, voire pas du tout, mais différents navigateurs gèrent les limites et l'éviction des données. Consultez la section Complément d'informations pour en savoir plus plus d'informations.

Termes liés aux bases de données indexées

Database (Base de données)
Niveau le plus élevé de IndexedDB. Il contient les magasins d'objets, qui à leur tour contenant les données que vous souhaitez conserver. Vous pouvez créer plusieurs bases de données avec quel que soit le nom de votre choix.
Magasin d'objets
Bucket individuel pour stocker des données, semblable aux tables des bases de données relationnelles. En règle générale, il existe un magasin d'objets pour chaque type (et non pour les données JavaScript). type) de données que vous stockez. Contrairement aux tables de base de données, les données JavaScript types de données d'un magasin n'ont pas besoin d'être cohérents. Par exemple, si une application dispose d'un magasin d'objets people contenant des informations sur trois personnes, ces Les propriétés d'âge des utilisateurs peuvent être 53, 'twenty-five' et unknown.
Index
Type de magasin d'objets permettant d'organiser des données dans un autre magasin d'objets (appelé un magasin d'objets de référence) par une propriété individuelle des données. L'index est utilisé pour récupérer les enregistrements dans le magasin d'objets à l'aide de cette propriété. Par exemple, si vous stocker des personnes, vous voudrez peut-être les récupérer plus tard par leur nom, leur âge ou votre animal préféré.
Opération
Interaction avec la base de données.
Transaction
Wrapper autour d'une opération ou d'un groupe d'opérations qui garantit la base de données l'intégrité. Si l'une des actions d'une transaction échoue, aucune d'entre elles n'est appliquée et la base de données revient à l'état dans lequel elle se trouvait avant la transaction a commencé. Toutes les opérations de lecture ou d'écriture dans IndexedDB doivent faire partie d'une transaction. Cela permet des opérations atomiques de lecture-modification-écriture sans risque de conflit avec d'autres threads agissant sur la base de données en même temps.
Cursor
Mécanisme d'itération sur plusieurs enregistrements d'une base de données.

Vérifier la compatibilité avec IndexedDB

La base de données IndexedDB est presque compatible de manière universelle. Cependant, si vous utilisez d'anciennes versions de navigateur, la prise en charge de détection des caractéristiques, au cas où. Le plus simple est de consulter les window objet:

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();

Ouvrir une base de données

Avec IndexedDB, vous pouvez créer plusieurs bases de données avec les noms de votre choix. Si une base de données n'existe pas lorsque vous essayez de l'ouvrir, créés automatiquement. Pour ouvrir une base de données, utilisez la méthode openDB() de la bibliothèque idb:

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();

Cette méthode renvoie une promesse qui renvoie vers un objet de base de données. Lorsque vous utilisez la openDB(), fournissez un nom, un numéro de version et un objet d'événement à définir la base de données.

Voici un exemple de la méthode openDB() en contexte:

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();

Vérifiez la compatibilité avec IndexedDB en haut de la fonction anonyme. Ce quitte la fonction si le navigateur n'est pas compatible avec IndexedDB. Si la fonction peut continue, elle appelle la méthode openDB() pour ouvrir une base de données nommée 'test-db1'. Dans cet exemple, l'objet "Events" (Événements) facultatif a été omis pour conserver est simple, mais vous devez le spécifier pour effectuer des tâches significatives avec IndexedDB.

Utiliser des magasins d'objets

Une base de données IndexedDB contient un ou plusieurs magasins d'objets, qui possèdent chacun un une colonne pour une clé et une autre colonne pour les données associées à cette clé.

Créer des magasins d'objets

Une base de données IndexedDB bien structurée doit comporter un magasin d'objets pour chaque type de données qui doivent être persistantes. Par exemple, un site dont les utilisateurs restent les profils et les notes peuvent avoir un magasin d'objets people contenant person et un magasin d'objets notes contenant des objets note.

Pour garantir l'intégrité de la base de données, vous ne pouvez créer ou supprimer des magasins d'objets que dans le d'événement dans un appel openDB(). L'objet "Events" expose une upgrade() qui vous permet de créer des magasins d'objets. Appelez la méthode createObjectStore() dans la méthode upgrade() pour créer le magasin d'objets:

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();

Cette méthode utilise le nom du magasin d'objets et une configuration qui vous permet de définir différentes propriétés pour le magasin d'objets.

Voici un exemple d'utilisation de 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();

Dans cet exemple, un objet "Events" est transmis à la méthode openDB() pour créer le magasin d'objets. Comme précédemment, le travail de création du magasin d'objets est terminé. dans la méthode upgrade() de l'objet événement. Toutefois, comme le navigateur génère une erreur s'affiche si vous essayez de créer un magasin d'objets qui existe déjà, nous vous conseillons encapsulant la méthode createObjectStore() dans une instruction if qui vérifie si le magasin d'objets existe. Dans le bloc if, appelez createObjectStore() pour créer un magasin d'objets nommé 'firstOS'.

Définir des clés primaires

Lorsque vous définissez des magasins d'objets, vous pouvez définir la façon dont les données sont identifiées de manière unique à l'aide d'une clé primaire. Vous pouvez définir une clé primaire en définissant ou à l'aide d'un générateur de clés.

Un chemin d'accès à la clé est une propriété qui existe toujours et qui contient une valeur unique. Pour Dans le cas d'un magasin d'objets people, vous pouvez choisir l'adresse e-mail comme chemin d'accès de la clé:

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();

Cet exemple crée un magasin d'objets appelé 'people' et attribue le email comme clé primaire dans l'option keyPath.

Vous pouvez également utiliser un générateur de clés tel que autoIncrement. Le générateur de clés crée une valeur unique pour chaque objet ajouté au magasin d'objets. Par défaut, Si vous ne spécifiez pas de clé, IndexedDB crée une clé et la stocke séparément à partir des données.

L'exemple suivant crée un magasin d'objets appelé 'notes' et définit le touche primaire à attribuer automatiquement sous la forme d'un nombre incrémenté automatiquement:

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();

L'exemple suivant est semblable à l'exemple précédent, mais cette fois, une valeur d'incrémentation automatique est explicitement attribuée à une propriété nommée '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();

Le choix de la méthode à utiliser pour définir la clé dépend de vos données. Si votre comporte une propriété qui est toujours unique, vous pouvez lui attribuer la propriété keyPath pour appliquer cette unicité. Sinon, utilisez une valeur d'incrémentation automatique.

Le code suivant crée trois magasins d'objets montrant les différentes manières définir des clés primaires dans les magasins d'objets:

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();

Définir des index

Les index sont un type de magasin d'objets utilisé pour récupérer des données de la référence en fonction d'une propriété spécifiée. Un index se trouve dans l'objet de référence stockent et contiennent les mêmes données, mais utilise la propriété spécifiée au lieu de la clé primaire du magasin de référence. Les index doivent être créés vous créez vos magasins d'objets. Vous pouvez l'utiliser pour définir une contrainte unique vos données.

Pour créer un index, appelez la méthode createIndex() sur une instance de magasin d'objets:

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();

Cette méthode crée et renvoie un objet index. La méthode createIndex() sur l'instance du magasin d'objets utilise le nom du nouvel index comme et le deuxième argument désigne la propriété des données à utiliser de l'index. L'argument final vous permet de définir deux options qui déterminent "index" fonctionne: unique et multiEntry. Si unique est défini sur true, le index n'autorise pas les valeurs en double pour une même clé. Suivant, multiEntry détermine le comportement de createIndex() lorsque la propriété indexée est un tableau. Si est défini sur true, createIndex() ajoute une entrée dans l'index pour chaque tableau . Sinon, il ajoute une seule entrée contenant le tableau.

Exemple :

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();

Dans cet exemple, les magasins d'objets 'people' et 'notes' ont des index. À créez les index, attribuez d'abord le résultat de createObjectStore() (un objet l'objet store) à une variable afin que vous puissiez appeler createIndex() sur celle-ci.

Comment utiliser les données

Cette section explique comment créer, lire, mettre à jour et supprimer des données. Ces sont toutes asynchrones et utilisent des promesses où l'API IndexedDB utilise requêtes. Cela simplifie l'API. Au lieu d'écouter les événements déclenchés par la requête, vous pouvez appeler .then() sur l'objet de base de données renvoyé par openDB() pour démarrer les interactions avec la base de données, ou await son création.

Toutes les opérations de données dans IndexedDB sont effectuées au sein d'une transaction. Chaque se présente sous la forme suivante:

  1. Obtenir un objet de base de données
  2. Ouvrir la transaction sur la base de données.
  3. Ouvrir le magasin d'objets lors de la transaction
  4. Effectuer des opérations sur un magasin d'objets

Une transaction peut être considérée comme un wrapper sécurisé pour une opération ou un groupe. des opérations. Si l'une des actions d'une transaction échoue, toutes les les actions sont annulés. Les transactions sont spécifiques à un ou plusieurs magasins d'objets, que vous définissez à l'ouverture de la transaction. Ils peuvent être en lecture seule ou en lecture seule et écrire. Cela signifie que les opérations au sein de la transaction lisent ou non des données ou d’apporter une modification à la base de données.

Créer des données

Pour créer des données, appelez la méthode add(). sur l'instance de base de données et transmettez les données que vous souhaitez ajouter. add() le premier argument de la méthode est le magasin d'objets auquel vous voulez ajouter les données. Le deuxième argument est un objet contenant les champs et les données associées que vous souhaitez à ajouter. Voici l'exemple le plus simple, dans lequel une seule ligne de données est ajoutée:

import {openDB} from 'idb';

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

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

addItemToStore();

Chaque appel add() se produit au cours d'une transaction. Par conséquent, même si la promesse est résolue avec succès, cela ne signifie pas nécessairement que l'opération a fonctionné. Pour vous assurer l'opération d'ajout, vous devez vérifier si l'intégralité la transaction a été effectuée à l'aide de la méthode transaction.done(). Il s'agit d'un promesse qui se résout une fois la transaction terminée et qui la rejette si les erreurs de transaction. Vous devez effectuer cette vérification pour toutes les opérations d'écriture opérations, car c'est le seul moyen de savoir que les modifications apportées à la base de données s'est produit.

Le code suivant illustre l'utilisation de la méthode add() dans une transaction:

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();

Après avoir ouvert la base de données (et créé un magasin d'objets si nécessaire), vous aurez besoin pour ouvrir une transaction en appelant la méthode transaction(). Cette méthode accepte un argument pour le magasin sur lequel vous souhaitez effectuer la transaction, ainsi que pour le mode. Ici, nous souhaitons écrire au magasin. Cet exemple spécifie 'readwrite'.

L'étape suivante consiste à ajouter des articles au magasin dans le cadre de la transaction. Dans l'exemple précédent, nous traitons trois opérations sur le 'foods' qui renvoient chacun une promesse:

  1. J'ajoute l'enregistrement d'un délicieux sandwich.
  2. Ajout d'un enregistrement pour quelques œufs.
  3. Indique que la transaction est terminée (tx.done).

Comme toutes ces actions sont toutes fondées sur des promesses, nous devons attendre que toutes pour terminer. Si vous passez ces promesses Promise.all permet d'y parvenir de manière agréable et ergonomique. Promise.all accepte un tableau de promesses et se termine lorsque toutes les promesses qui lui ont été transmises sont résolues.

Pour les deux enregistrements ajoutés, l'interface store de l'instance de transaction appelle add() et lui transmet les données. Vous pouvez await l'appel Promise.all afin qu'elle se termine une fois la transaction terminée.

Lire des données

Pour lire des données, appelez la méthode get() sur l'instance de base de données que vous récupérez à l'aide de la méthode openDB(). get() prend le nom du magasin et la valeur de clé primaire de l'objet que vous que vous souhaitez récupérer. Voici un exemple de base:

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();

Comme pour add(), la méthode get() renvoie une promesse. Vous pouvez donc la await si que vous préférez, ou utilisez le rappel .then() de la promesse.

L'exemple suivant utilise la méthode get() sur le'test-db4' Magasin d'objets 'foods' pour obtenir une seule ligne par la clé primaire '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();

Il est assez simple de récupérer une seule ligne de la base de données : la base de données et spécifier le magasin d'objets et la valeur de clé primaire de la ligne que vous vous souhaitez obtenir des données. Comme la méthode get() renvoie une promesse, vous pouvez await.

Mettre à jour des données

Pour mettre à jour les données, appelez la méthode put() sur le magasin d'objets. La méthode put() est semblable à la méthode add(). et peut également être utilisé à la place de add() pour créer des données. Voici un exemple de base de l'utilisation de put() pour mettre à jour une ligne dans un magasin d'objets en fonction de sa valeur de clé primaire:

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();

Comme les autres méthodes, cette méthode renvoie une promesse. Vous pouvez également utiliser put() comme dans le cadre d'une transaction. Voici un exemple utilisant le magasin 'foods' vu précédemment qui met à jour le prix du sandwich et des œufs:

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();

La façon dont les éléments sont mis à jour dépend de la manière dont vous définissez une clé. Si vous définissez un keyPath, chaque ligne du magasin d'objets est associée à une clé intégrée. L'étape précédente dans cet exemple met à jour les lignes en fonction de cette clé, et lorsque vous mettez à jour des lignes dans vous devez spécifier cette clé pour mettre à jour l'élément approprié dans un magasin d'objets. Vous pouvez également créer une clé hors ligne en définissant une autoIncrement comme clé primaire.

Supprimer des données

Pour supprimer des données, appelez la fonction delete() sur le magasin d'objets:

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();

Comme pour add() et put(), vous pouvez l'utiliser dans le cadre d'une transaction:

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();

La structure de l'interaction avec la base de données est la même que pour opérations. N'oubliez pas de vérifier que l'intégralité de la transaction est terminée d'ici le en incluant la méthode tx.done dans le tableau que vous transmettez à Promise.all.

Obtenir toutes les données

Jusqu'à présent, vous n'avez récupéré les objets du magasin qu'un par un. Vous pouvez également récupérer toutes les données, ou un sous-ensemble, d'un index ou d'un magasin d'objets à l'aide de soit la méthode getAll(), soit les curseurs.

La méthode getAll()

Le moyen le plus simple de récupérer toutes les données d'un magasin d'objets consiste à appeler getAll(). sur le magasin ou l'index d'objets, comme ceci:

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();

Cette méthode renvoie tous les objets du magasin d'objets, sans contraintes. quelle qu'elle soit. C'est le moyen le plus direct d'obtenir toutes les valeurs d'un magasin d'objets, mais aussi le moins flexible.

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();

Cet exemple appelle getAll() sur le magasin d'objets 'foods'. Cela renvoie tous les les objets de 'foods', classés selon la clé primaire.

Utiliser les curseurs

Les curseurs constituent un moyen plus flexible de récupérer plusieurs objets. Un curseur sélectionne chaque objet d'un magasin ou d'un index un par un, ce qui vous permet avec les données lorsqu'elles sont sélectionnées. Les curseurs, comme les autres opérations de base de données, dans les transactions.

Pour créer un curseur, appelez openCursor(). sur le magasin d'objets dans le cadre d'une transaction. Utilisation du magasin 'foods' depuis exemples précédents, il s'agit de la manière de faire avancer un curseur dans toutes les lignes de données dans un magasin d'objets:

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();

Dans ce cas, la transaction est ouverte en mode 'readonly' et son La méthode openCursor est appelée. Dans une boucle while ultérieure, la ligne au niveau les propriétés key et value peuvent être lues à la position actuelle du curseur, et vous pouvez agir sur ces valeurs de la manière qui convient le mieux l'application. Lorsque vous êtes prêt, vous pouvez appeler le continue() de l'objet cursor pour passer à la ligne suivante, et la boucle while se termine lorsque le curseur atteint la fin du jeu de données.

Utiliser des curseurs avec des plages et des index

Les index vous permettent d'extraire les données d'un magasin d'objets à l'aide d'une propriété autre que la clé primaire. Vous pouvez créer un index sur n'importe quelle propriété, qui devient le keyPath. pour l'index, spécifiez une plage pour cette propriété, puis récupérez les données dans la plage à l'aide de getAll() ou d'un curseur.

Définissez votre plage à l'aide de l'objet IDBKeyRange. et l'un des éléments suivants méthodes:

Les méthodes upperBound() et lowerBound() spécifient les limites supérieure et inférieure. de la plage.

IDBKeyRange.lowerBound(indexKey);

soit :

IDBKeyRange.upperBound(indexKey);

Chacun accepte un argument: la valeur keyPath de l'index pour l'élément souhaité. pour spécifier la limite supérieure ou inférieure.

La méthode bound() spécifie à la fois une limite supérieure et inférieure:

IDBKeyRange.bound(lowerIndexKey, upperIndexKey);

La plage de ces fonctions est inclusive par défaut, ce qui signifie qu'elle inclut les données spécifiées comme limites de la plage. Pour omettre ces valeurs, spécifiez la plage comme exclusive en transmettant true comme deuxième argument pour lowerBound() ou upperBound(), ou comme troisième et quatrième arguments de bound(), pour les limites inférieure et supérieure, respectivement.

L'exemple suivant utilise un index sur la propriété 'price' de l'objet 'foods' Google Store. Le magasin dispose désormais d'un formulaire associé à deux entrées pour la les limites supérieure et inférieure de la plage. Utilisez le code suivant pour trouver des aliments avec entre ces limites:

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);

L'exemple de code commence par obtenir les valeurs des limites et vérifie si les limites existent. Le bloc de code suivant décide quelle méthode utiliser pour limiter la plage en fonction des valeurs. Dans l'interaction avec la base de données, ouvrez le magasin d'objets sur le comme d'habitude, puis ouvrez l'index 'price' sur le magasin d'objets. La L'index 'price' vous permet de rechercher des éléments par prix.

Le code ouvre ensuite un curseur sur l'index et transmet la plage. Curseur renvoie une promesse représentant le premier objet de la plage, ou undefined si aucune donnée n'est dans la plage. La méthode cursor.continue() renvoie une curseur représentant l'objet suivant et qui continue à travers la boucle atteindre la fin de la plage.

Gestion des versions de bases de données

Lorsque vous appelez la méthode openDB(), vous pouvez spécifier le numéro de version de la base de données dans le deuxième paramètre. Dans tous les exemples de ce guide, la version a été définie sur 1, mais vous pouvez mettre à niveau une base de données vers une nouvelle version si nécessaire le modifier d'une manière ou d'une autre. Si la version spécifiée est supérieure à celle du la base de données existante, le rappel upgrade dans l'objet d'événement s'exécute ce qui vous permet d'ajouter des magasins d'objets et des index à la base de données.

L'objet db du rappel upgrade possède une propriété oldVersion spéciale. qui indique le numéro de version de la base de données à laquelle le navigateur a accès. Vous pouvez transmettre ce numéro de version dans une instruction switch pour exécuter des blocs de code dans le rappel upgrade en fonction de la version de base de données existante numéro. Exemple :

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');
    }
  }
});

Dans cet exemple, la dernière version de la base de données est définie sur 2. Lorsque ce code s'exécute en premier, la base de données n'existe pas encore dans le navigateur. oldVersion correspond à 0, et l'instruction switch commence à case 0. Dans cet exemple, ce ajoute un magasin d'objets 'store' à la base de données.

Important: Dans les instructions switch, il y a généralement un break après chaque case mais qui n'est délibérément pas utilisé ici. De cette façon, a quelques versions de retard. Si elle n'existe pas, le code continue le reste des blocs case jusqu'à ce qu'il soit à jour. Donc, dans cet exemple, le navigateur continue de s'exécuter via case 1, ce qui crée un index name sur le Magasin d'objets store.

Pour créer un index 'description' sur le magasin d'objets 'store', mettez à jour la numéro de version et ajoutez un nouveau bloc case comme suit:

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');
    }
  }
});

Si la base de données que vous avez créée dans l’exemple précédent existe toujours dans le navigateur, Lors de l'exécution, oldVersion est défini sur 2. Le navigateur ignore case 0 et case 1 et exécute le code dans case 2, qui crée un description. de l'index. Ensuite, le navigateur dispose d'une base de données (version 3) contenant un store magasin d'objets avec les index name et description.

Documentation complémentaire

Les ressources suivantes fournissent plus d'informations et de contexte sur l'utilisation de IndexedDB.

Documentation IndexedDB

Limites de stockage des données