CreateObjectStore: примеры (JAVASCRIPT)
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 создания хранилищ остался стабильным и обратно совместимым с более ранними версиями.
Расширенные примеры использования
Создание хранилища с ключевым путем и одновременное определение индексов:
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 });
};Использование составного ключа для организации иерархических данных:
let store = db.createObjectStore('Messages', {
keyPath: ['chatId', 'timestamp']
});
// Ключом будет массив [chatId, timestamp]
store.add({ text: 'Hello' }, [1001, 1640995200000]);Создание хранилища с генератором ключей и без keyPath. Ключ генерируется явно:
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
Обработка ситуации, когда база данных может уже содержать хранилище с таким именем (использование проверки существования):
if (!db.objectStoreNames.contains('MyStore')) {
db.createObjectStore('MyStore', { keyPath: 'id' });
} else {
console.log('Хранилище уже существует.');
}