UNPKG

wise-json-db

Version:

Blazing fast, crash-proof embedded JSON database for Node.js with batch operations, TTL, indexes, and segmented checkpointing.

347 lines (255 loc) 23.5 kB
# 📦 WiseJSON DB (Мудрая JSON База Данных) ![WiseJSON Логотип](logo.png) [npm version](https://npmjs.org/package/wise-json-db) [License](https://github.com/Xzdes/WiseJSON/blob/master/LICENSE) [Node.js CI](https://github.com/Xzdes/WiseJSON/actions/workflows/nodejs.yml) **WiseJSON DB** это невероятно быстрая, отказоустойчивая встраиваемая JSON-база данных для Node.js с поддержкой пакетных операций, TTL (время жизни), индексов и сегментированных чекпоинтов. Разработана для высокой производительности, надежности и простоты интеграции в ваши Node.js приложения. --- ## 🚀 Ключевые особенности * **Высокая производительность:** Оптимизированные операции чтения и записи. * **Отказоустойчивость и Надежность:** * **WAL (Write-Ahead Logging):** Все изменения сначала записываются в журнал для гарантированного восстановления данных после сбоев. * **Чекпоинты:** Периодическое сохранение состояния базы данных (снапшоты) для быстрого восстановления. * **Сегментированные чекпоинты:** Автоматическое разделение данных больших коллекций на сегменты при создании чекпоинта для лучшей производительности и управления памятью. * **Управляемое количество хранимых чекпоинтов.** * **Атомарная запись файлов:** Безопасное сохранение JSON и метаданных через временные файлы с последующим переименованием. * **Предварительные проверки уникальности:** Для операций `insert`, `insertMany` и `update` проверки на нарушение уникальных индексов выполняются до записи в WAL, предотвращая сохранение заведомо некорректных данных. * **ACID-транзакции:** Поддержка атомарных транзакций между несколькими коллекциями, обеспечивая консистентность изменений. * **Индексы:** Уникальные и неуникальные индексы по полям документов для значительного ускорения операций поиска. * **TTL (Time-To-Live):** Автоматическое удаление устаревших документов на основе времени жизни или точной даты истечения. * **Пакетные операции:** Эффективные `insertMany` и `updateMany` для массовой работы с данными. * **Встраиваемая и файловая:** Хранит данные локально в файловой системе, не требует отдельного сервера или процесса. * **Простой и интуитивный API:** Легко начать работу с коллекциями и документами. * **Инструменты:** * **Базовый CLI (`wise-json`):** Для выполнения основных операций с базой данных из командной строки. * **Data Explorer (веб-интерфейс и расширенный CLI `wisejson-explorer`):** Для удобного просмотра, экспорта и управления данными и индексами. * **Легковесная:** Минимальное количество внешних зависимостей (только `uuid` и `proper-lockfile`). * **Graceful Shutdown:** Автоматическое корректное сохранение всех данных при штатном завершении работы приложения. * **Кастомный генератор ID:** Позволяет определить собственную функцию для генерации значений поля `_id`. * **Безопасность многопроцессной работы:** Использует `proper-lockfile` для предотвращения гонок данных при доступе из нескольких процессов к одной БД. --- ## 📦 Зависимости WiseJSON DB использует всего две runtime-зависимости: * [`uuid`](https://www.npmjs.com/package/uuid) для генерации уникальных идентификаторов по умолчанию. * [`proper-lockfile`](https://www.npmjs.com/package/proper-lockfile) для безопасной блокировки файлов, обеспечивающей корректную работу при доступе из нескольких процессов. Обе зависимости устанавливаются автоматически при установке основного пакета: ```bash npm install wise-json-db ``` Если вы используете кастомную систему сборки или подключаете WiseJSON DB как часть более сложного бандла, убедитесь, что эти пакеты также включены в ваши зависимости: ```bash npm install uuid proper-lockfile ``` --- ## 💡 Почему WiseJSON DB? * **Надежность превыше всего:** Механизмы WAL, чекпоинтов и атомарной записи файлов спроектированы для максимальной сохранности ваших данных даже в случае непредвиденных сбоев. * **Скорость доступа к данным:** Индексы и оптимизированные операции обеспечивают быстрый поиск и модификацию данных. * **Простота интеграции и использования:** Не требует настройки внешних сервисов. Начните работу с данными за считанные минуты. * **Полный контроль над данными:** Ваши данные хранятся локально, и вы полностью контролируете к ним доступ. * **Гибкость JSON:** Нативно работает с JSON, позволяя хранить сложные и вложенные структуры данных без необходимости предварительного определения схемы. --- ## 📥 Установка ```bash npm install wise-json-db # или yarn add wise-json-db ``` --- ## 📚 Основное использование (API) ```javascript const WiseJSON = require('wise-json-db'); const path = require('path'); // Укажите путь, где будет храниться ваша база данных const dbPath = path.resolve(__dirname, 'myDataBase'); async function main() { // Инициализация базы данных с опциями const db = new WiseJSON(dbPath, { ttlCleanupIntervalMs: 60000, // Проверять TTL каждые 60 секунд checkpointIntervalMs: 300000 // Делать чекпоинт каждые 5 минут }); await db.init(); // Важно дождаться инициализации БД // Получение (или создание) коллекции 'users' const users = await db.getCollection('users'); // Очистим для предсказуемого результата await users.clear(); // Создаем индексы для быстрых запросов await users.createIndex('city'); // Обычный индекс await users.createIndex('email', { unique: true }); // Уникальный индекс console.log('Индексы созданы:', await users.getIndexes()); // Вставка одного документа await users.insert({ name: 'Алиса', email: 'alice@example.com', age: 30, city: 'Москва' }); // Пакетная вставка нескольких документов await users.insertMany([ { name: 'Борис', email: 'bob@example.com', age: 24, city: 'Лондон' }, { name: 'Вера', email: 'vera@example.com', age: 35, city: 'Париж', tags: ['dev', 'котики'] } ]); console.log(`Всего пользователей после вставки: ${await users.count()}`); // Поиск документов с помощью объекта-фильтра (современный, рекомендуемый способ) const usersFromLondon = await users.find({ city: 'Лондон' }); console.log('Пользователи из Лондона:', usersFromLondon); // Поиск одного документа с операторами const devUser = await users.findOne({ tags: 'dev', age: { $gt: 30 } }); console.log('Первый разработчик старше 30:', devUser); // Обновление документа по ID if (devUser) { const updatedDevUser = await users.update(devUser._id, { age: devUser.age + 1, lastLogin: new Date().toISOString() }); console.log('Обновленный разработчик:', updatedDevUser); } // Пакетное обновление документов с помощью фильтра и операторов обновления const updateResult = await users.updateMany( { age: { $gte: 25 } }, // Фильтр: найти пользователей 25 лет и старше { $set: { status: 'active' } } // Оператор обновления: установить им статус ); console.log(`Обновлено ${updateResult.modifiedCount} пользователей (статус active).`); // Вставка документа с TTL (время жизни 5 секунд) await users.insert({ email: 'temp@example.com', message: 'Это сообщение самоуничтожится через 5 секунд', ttl: 5000 // в мс от createdAt }); console.log('Вставлены временные данные.'); // Пример транзакции const txn = db.beginTransaction(); try { const logsCollection = await db.collection('logs'); await logsCollection.initPromise; // Операции внутри транзакции await txn.collection('users').insert({ name: 'Диана', email: 'diana@example.com', age: 28 }); await txn.collection('logs').insert({ action: 'USER_CREATED', user: 'Диана', timestamp: Date.now() }); await txn.commit(); // Применяем транзакцию console.log('Транзакция успешно завершена.'); } catch (error) { await txn.rollback(); // Откатываем изменения в случае ошибки console.error('Ошибка транзакции, изменения отменены:', error); } // Закрытие базы данных (важно для сохранения всех данных) await db.close(); console.log('База данных закрыта.'); } main().catch(console.error); ``` --- ## ⚙️ Конфигурация При создании экземпляра `WiseJSON` вы можете передать объект с опциями: ```javascript const db = new WiseJSON('/путь/к/вашей/бд', { // Интервал автоматической очистки документов с истекшим TTL миллисекундах) // По умолчанию: 60000 (1 минута) ttlCleanupIntervalMs: 60000, // Интервал автоматического создания чекпоинтов миллисекундах) // 0 или отрицательное значение отключает чекпоинты по таймеру. // По умолчанию: 300000 (5 минут) checkpointIntervalMs: 300000, // Максимальное количество записей в WAL-файле перед принудительным созданием чекпоинта. // 0 или отрицательное значение отключает этот триггер. // По умолчанию: 1000 maxWalEntriesBeforeCheckpoint: 1000, // Максимальный размер одного сегмента данных в чекпоинте байтах). // Большие коллекции будут разбиты на несколько сегментов при создании чекпоинта. // По умолчанию: 2 * 1024 * 1024 (2MB) maxSegmentSizeBytes: 2097152, // Количество последних чекпоинтов, которые нужно хранить. Старые будут удаляться. // Минимальное значение: 1. // По умолчанию: 5 checkpointsToKeep: 5, // Пользовательская функция для генерации _id документов. // По умолчанию используется генератор на основе uuid. idGenerator: () => `my-custom-id-${Date.now()}-${Math.random().toString(36).slice(2)}`, // Опции для чтения WAL-файла при инициализации коллекции. // По умолчанию: { recover: false, strict: false } // recover: true - пытаться восстановить данные, пропуская поврежденные строки WAL выводом предупреждения). // strict: true - бросать ошибку при первой же ошибке парсинга строки WAL. // Если recover=false и strict=false (по умолчанию), поврежденные строки пропускаются с предупреждением. walReadOptions: { recover: true, strict: false }, }); ``` --- ## 🛠️ Интерфейс командной строки (CLI) WiseJSON DB включает два инструмента командной строки: ### 1️⃣ Базовый CLI: `wise-json` Предназначен для основных операций с базой данных. Устанавливается глобально или используется через `npx`. Примеры команд: ```bash # Помощь wise-json help # Список всех коллекций wise-json list # Информация о коллекции (статистика, индексы) wise-json info <имя_коллекции> # Вставка документа (JSON в виде строки) wise-json insert <имя_коллекции> '{"name":"Иван","age":30}' # Пакетная вставка из файла data.json wise-json insert-many <имя_коллекции> data.json # Пакетная вставка с TTL в 1 час wise-json insert-many <имя_коллекции> data.json --ttl 3600000 # Поиск документов (фильтр - JSON-строка с поддержкой операторов $gt, $lt, $in, $regex, $or, $and) wise-json find <имя_коллекции> '{"age":{"$gt":25}}' wise-json find <имя_коллекции> '{"$or":[{"city":"Москва"},{"tags":{"$in":["dev"]}}]}' # Получение документа по ID wise-json get <имя_коллекции> <ID_документа> # Удаление документа по ID wise-json remove <имя_коллекции> <ID_документа> # Полная очистка коллекции wise-json clear <имя_коллекции> # Экспорт коллекции в файл wise-json export <имя_коллекции> export_data.json # Импорт документов из файла в коллекцию wise-json import <имя_коллекции> import_data.json ``` **Переменные окружения для `wise-json`:** * `WISE_JSON_PATH`: Путь к директории базы данных (по умолчанию: `./wise-json-db-data`). * `WISE_JSON_LANG`: Язык интерфейса CLI (`ru` или `en`, по умолчанию `en`). ### 2️⃣ Расширенный CLI и Data Explorer: `wisejson-explorer` Этот инструмент предоставляет более продвинутые возможности для работы с данными, включая экспорт в CSV, управление индексами, а также служит основой для веб-интерфейса Data Explorer. Примеры команд `wisejson-explorer`: ```bash # Помощь wisejson-explorer --help # Список коллекций wisejson-explorer list-collections # Просмотр документов коллекции с фильтрацией, сортировкой, пагинацией wisejson-explorer show-collection <имя_коллекции> --limit 5 --offset 0 --sort age --order desc --filter '{"city":"Москва"}' # Экспорт коллекции в JSON (по умолчанию) или CSV wisejson-explorer export-collection <имя_коллекции> data.json wisejson-explorer export-collection <имя_коллекции> data.csv --output csv # Импорт данных в коллекцию (режимы: append, replace) # Требует --allow-write для операций записи wisejson-explorer import-collection <имя_коллекции> data.json --mode replace --allow-write # Управление индексами wisejson-explorer list-indexes <имя_коллекции> wisejson-explorer create-index <имя_коллекции> <имя_поля> --unique --allow-write wisejson-explorer drop-index <имя_коллекции> <имя_поля> --allow-write ``` По умолчанию `wisejson-explorer` работает в режиме "только для чтения". Для выполнения операций, изменяющих данные (импорт, создание/удаление индексов), необходимо использовать флаг `--allow-write`. --- ## 🌐 Data Explorer (Веб-интерфейс) Для запуска веб-интерфейса Data Explorer используйте команду: ```bash node explorer/server.js # или, если установлен глобально или как зависимость проекта: wisejson-explorer-server ``` Веб-интерфейс будет доступен по адресу [http://127.0.0.1:3000](http://127.0.0.1:3000) (порт по умолчанию, может быть изменен через переменную окружения `PORT`). Data Explorer позволяет просматривать коллекции и документы, применять фильтры, сортировку и пагинацию. Для защиты доступа можно использовать переменные окружения `WISEJSON_AUTH_USER` и `WISEJSON_AUTH_PASS`. --- ## 🔒 Надежность и отказоустойчивость WiseJSON DB уделяет особое внимание сохранности данных: * **Write-Ahead Logging (WAL):** Каждая операция изменения данных (вставка, обновление, удаление) сначала записывается в специальный лог-файл (WAL). Только после успешной записи в WAL операция применяется к данным в памяти. В случае сбоя приложения или сервера, при следующем запуске WAL-файл будет прочитан, и все незавершенные, но залогированные операции будут применены, восстанавливая состояние базы данных до момента сбоя. * **Чекпоинты:** Периодически (или по достижении определенного объема WAL) создается полный снимок (чекпоинт) состояния всех данных коллекции. Это позволяет значительно ускорить процесс восстановления, так как нужно будет применять только те записи WAL, которые были сделаны *после* последнего успешного чекпоинта. Старые чекпоинты автоматически удаляются. * **Атомарная Запись Файлов:** При сохранении чекпоинтов и других важных файлов данных используется стратегия записи во временный файл с последующим атомарным переименованием. Это предотвращает порчу основного файла данных, если во время записи произойдет сбой. * **Блокировки Файлов:** Использование `proper-lockfile` обеспечивает корректную работу с файлами базы данных даже при одновременном доступе из нескольких процессов Node.js, предотвращая гонки данных и повреждение файлов. --- ## 🤝 Вклад в разработку (Contributing) Мы всегда рады вашему участию в улучшении WiseJSON DB! Вы можете помочь: * Сообщениями об ошибках (Bug reports) * Предложениями новых функций или улучшений (Feature suggestions) * Pull Request'ами с исправлениями или новым кодом Пожалуйста, ознакомьтесь с нашим гайдлайном для контрибьюторов (если он будет создан) или просто создавайте Issue на GitHub. --- ## 📄 Лицензия Проект распространяется под лицензией MIT. См. файл `LICENSE` для подробностей. Автор: Xzdes ([xzdes@yandex.ru](mailto:xzdes@yandex.ru)) ```