CreateObjectStore: примеры (JAVASCRIPT)

Метод createObjectStore: создание хранилищ в IndexedDB
Раздел: IndexedDB, Хранилище
createObjectStore(name: String, [options]: Object): IDBObjectStore

Основные сведения о createObjectStore

Метод createObjectStore() является частью API IndexedDB и применяется для создания хранилища объектов внутри базы данных. Хранилище объектов можно представить как таблицу в реляционной базе данных, предназначенную для сохранения записей в виде пар ключ-значение. Метод вызывается в контексте объекта IDBDatabase во время события onupgradeneeded, которое происходит при открытии базы данных с увеличенной версией.

Аргументы метода:

  • name (строка, обязательный): Уникальное имя создаваемого хранилища объектов.
  • optionalParameters (объект, необязательный): Объект конфигурации, который может содержать два свойства:
    • keyPath (строка, массив строк или null): Определяет путь к свойству в сохраняемом объекте, которое будет использоваться как первичный ключ. Если указан массив, то ключ считается составным. Значение null означает, что хранилище будет использовать внешний ключ.
    • autoIncrement (логическое значение, по умолчанию false): Если установлено в true, база данных автоматически генерирует возрастающий числовой ключ для новых записей.

Возвращаемое значение:

Метод возвращает новый объект IDBObjectStore, представляющий созданное хранилище. Этот объект можно сразу использовать для создания индексов.

Простые примеры применения

Создание хранилища с автоматическим ключом:

let request = indexedDB.open('MyDB', 1);
request.onupgradeneeded = function(event) {
  let db = event.target.result;
  let store = db.createObjectStore('Products', {
    autoIncrement: true
  });
  console.log(store.name);
};
// В консоли: 'Products'

Создание хранилища с ключом на основе свойства объекта:

let store = db.createObjectStore('Users', {
  keyPath: 'id'
});

Создание хранилища с составным ключом:

let store = db.createObjectStore('Orders', {
  keyPath: ['userId', 'orderId']
});

Создание хранилища без ключевого пути (ключ будет предоставляться явно при добавлении данных):

let store = db.createObjectStore('Logs', {
  keyPath: null
});

Похожие возможности в JavaScript

Для хранения данных на стороне клиента в JavaScript существуют и другие механизмы, но они не являются прямыми аналогами createObjectStore.

Web Storage (localStorage, sessionStorage)

Предоставляет простое хранение пар ключ-значение только строкового типа. Не поддерживает индексы, транзакции или сложные запросы. Подходит для небольших объемов простых данных.

Web SQL Database

Устаревший API, который предлагал реляционную модель базы данных с использованием SQL. Был удален из стандартов. IndexedDB с его нереляционной моделью является его преемником.

Cache API

Предназначен специально для хранения пар запрос-ответ, связанных с работой Service Workers. Не подходит для хранения произвольных структурированных данных приложения.

Аналоги в других языках и системах

Python (словарь или sqlite3)

В Python для хранения данных в памяти часто используется словарь. Для постоянного хранения - модуль sqlite3, который позволяет создавать таблицы с помощью SQL-команды CREATE TABLE.

import sqlite3
conn = sqlite3.connect('mydb.db')
cursor = conn.cursor()
cursor.execute('''CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)''')

PHP (PDO, SQL)

Работа с базами данных, такими как MySQL, осуществляется через расширение PDO и SQL-запросы.

$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$pdo->exec('CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255))');

MySQL

Непосредственно язык определения данных (DDL) SQL.

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255)
);

Основное отличие IndexedDB от SQL-подходов заключается в объектной модели данных вместо реляционной и асинхронной операции, основанной на событиях.

Распространенные ошибки

Вызов метода вне события onupgradeneeded

let db = await indexedDB.open('MyDB', 1);
db.createObjectStore('Store', { keyPath: 'id' }); // DOMException
// DOMException: Failed to execute 'createObjectStore' on 'IDBDatabase': 
// The database is not running a version change transaction.

Попытка создать хранилище с уже существующим именем

// При обновлении версии базы
let store1 = db.createObjectStore('MyStore', { keyPath: 'id' });
let store2 = db.createObjectStore('MyStore', { keyPath: 'name' }); // Ошибка
// DOMException: Failed to execute 'createObjectStore' on 'IDBDatabase': 
// An object store with the specified name already exists.

Некорректное указание keyPath

// Если keyPath указывает на свойство, которого нет в объекте
let store = db.createObjectStore('Test', { keyPath: 'nonExistentProp' });
let request = store.add({ data: 123 }); // Ошибка при добавлении
// DataError: Failed to execute 'add' on 'IDBObjectStore': 
// Evaluating the object store's key path yielded 'undefined'.

История изменений

Спецификация IndexedDB 3.0 (2021) не внесла существенных изменений в сигнатуру или поведение метода createObjectStore(). Основные обновления были сосредоточены на добавлении новых возможностей, таких как промисы (indexedDB.databases()), но базовый API создания хранилищ остался стабильным и обратно совместимым с более ранними версиями.

Расширенные примеры использования

Создание хранилища с ключевым путем и одновременное определение индексов:

Пример javascript
request.onupgradeneeded = function(event) {
  let db = event.target.result;
  let store = db.createObjectStore('Books', {
    keyPath: 'isbn'
  });
  store.createIndex('by_author', 'author', { unique: false });
  store.createIndex('by_year', 'year', { unique: false });
};

Использование составного ключа для организации иерархических данных:

Пример javascript
let store = db.createObjectStore('Messages', {
  keyPath: ['chatId', 'timestamp']
});
// Ключом будет массив [chatId, timestamp]
store.add({ text: 'Hello' }, [1001, 1640995200000]);

Создание хранилища с генератором ключей и без keyPath. Ключ генерируется явно:

Пример javascript
let store = db.createObjectStore('Events', {
  autoIncrement: true,
  keyPath: null
});
// Ключ будет сгенерирован автоматически, но не будет свойством объекта
let requestAdd = store.add({ type: 'click', x: 100, y: 200 });
requestAdd.onsuccess = function() {
  console.log('Ключ добавленной записи:', requestAdd.result);
};
// Ключ добавленной записи: 1

Обработка ситуации, когда база данных может уже содержать хранилище с таким именем (использование проверки существования):

Пример javascript
if (!db.objectStoreNames.contains('MyStore')) {
  db.createObjectStore('MyStore', { keyPath: 'id' });
} else {
  console.log('Хранилище уже существует.');
}

JS createObjectStore function comments

En
CreateObjectStore Creates and returns a new object store or index