{"id":11252,"library":"lokijs","title":"LokiJS In-Memory Database","description":"LokiJS is a fast, document-oriented JavaScript in-memory database designed for various environments including browsers, Node.js, and NativeScript. It functions by storing JavaScript objects as documents in a NoSQL fashion, enabling high-performance retrieval through indexing and dynamic views. Currently at version 1.5.12, its release cadence appears infrequent, with the last major update several years ago. Key differentiators include its small footprint, suitability for client-side session stores, and built-in persistence adapters (like localStorage, IndexedDB, or filesystem) that can be extended with custom solutions. It prioritizes speed by maintaining unique and binary indexes and offering dynamic views for frequently accessed data subsets, making it ideal for performance-critical applications where data can reside primarily in memory.","status":"maintenance","version":"1.5.12","language":"javascript","source_language":"en","source_url":"https://github.com/techfort/LokiJS","tags":["javascript","document-oriented","mmdb","json","nosql","lokijs","in-memory","indexeddb"],"install":[{"cmd":"npm install lokijs","lang":"bash","label":"npm"},{"cmd":"yarn add lokijs","lang":"bash","label":"yarn"},{"cmd":"pnpm add lokijs","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"LokiJS primarily uses a default export for the main Loki class in ESM environments, though it's fundamentally a CommonJS library. Accessing named exports like `Loki` directly often fails without proper bundler configuration for CJS interoperability.","wrong":"import { Loki } from 'lokijs';","symbol":"Loki","correct":"import Loki from 'lokijs';"},{"note":"For CommonJS, the `require('lokijs')` call returns the Loki class constructor directly, not an object with named exports.","wrong":"const { Loki } = require('lokijs');","symbol":"Loki","correct":"const Loki = require('lokijs');"},{"note":"Persistence adapters are typically located in the `src` subdirectory and often require direct import from their specific file paths, rather than being named exports from the main `lokijs` package.","wrong":"import { LokiLocalStorageAdapter } from 'lokijs';","symbol":"LokiLocalStorageAdapter","correct":"import LokiLocalStorageAdapter from 'lokijs/src/loki-local-storage-adapter';"}],"quickstart":{"code":"import Loki from 'lokijs';\nimport LokiLocalStorageAdapter from 'lokijs/src/loki-local-storage-adapter';\n\nconst dbName = 'myCoolDatabase.db';\nconst adapter = new LokiLocalStorageAdapter(dbName);\n\nconst db = new Loki(dbName, {\n  adapter: adapter,\n  autoload: true,\n  autoloadCallback: databaseInitialize,\n  autosave: true,\n  autosaveInterval: 4000\n});\n\nfunction databaseInitialize() {\n  let users = db.getCollection('users');\n  if (users === null) {\n    users = db.addCollection('users', { unique: ['email'] });\n  }\n\n  // Check if there's any data, if not, insert some\n  if (users.count() === 0) {\n    users.insert({ name: 'Alice', email: 'alice@example.com', age: 30 });\n    users.insert({ name: 'Bob', email: 'bob@example.com', age: 24 });\n    console.log('Initial data inserted.');\n  } else {\n    console.log('Database already contains data.');\n  }\n\n  const allUsers = users.find();\n  console.log('All users:', allUsers);\n\n  const youngUsers = users.find({ age: { '$lt': 25 } });\n  console.log('Users younger than 25:', youngUsers);\n\n  // Update an existing user\n  const alice = users.findOne({ name: 'Alice' });\n  if (alice) {\n    alice.age = 31;\n    users.update(alice);\n    console.log('Alice updated:', users.findOne({ name: 'Alice' }));\n  }\n\n  // Ensure data is saved after modifications if autosave is off or before manual exit\n  // db.saveDatabase(); // Autosave handles this in this example\n}\n\nconsole.log('LokiJS database initialized or loaded.');","lang":"javascript","description":"This quickstart demonstrates how to initialize a LokiJS in-memory database, configure it with the LocalStorage adapter for persistence, add a collection with a unique constraint, insert documents, and perform basic queries and updates. It includes an `autoload` and `autosave` setup to manage data lifecycle across sessions."},"warnings":[{"fix":"For new projects, consider modern alternatives like RxDB or other actively maintained in-memory databases. For existing projects, be aware of the potential for limited support or future breaking changes without clear migration paths.","message":"Some external sources (e.g., database.guide) claim LokiJS was abandoned in 2022 and its official website redirects to RxDB, suggesting a lack of active development or future deprecation in favor of alternatives. While the GitHub repository shows some recent minor commits, the discrepancy and the outdated README (referencing v1.3 while npm is v1.5.12) indicate potential long-term maintenance uncertainty and recommend evaluating alternatives like RxDB for new projects.","severity":"breaking","affected_versions":">=1.5.0"},{"fix":"Always initialize LokiJS with a suitable persistence adapter (e.g., `LokiLocalStorageAdapter`, `LokiIndexedAdapter`, `LokiFsAdapter` for Node.js) and enable `autoload: true` and `autosave: true` options to prevent data loss. Remember to manually call `db.saveDatabase()` before application exit if `autosave` is not active or for immediate writes.","message":"LokiJS is an in-memory database, meaning data is lost upon application restart or browser refresh unless a persistence adapter is explicitly configured. Default behavior is purely in-memory.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"If multi-tab support is required, consider wrapping LokiJS with a solution that handles leader election or provides a more robust multi-instance synchronization mechanism, such as the RxDB LokiJS plugin which addresses this issue. Alternatively, ensure only one tab is actively writing to the database.","message":"Using plain LokiJS across multiple browser tabs can lead to data loss due to instances overwriting each other's persistence. LokiJS loads data in bulk and periodically persists it, which is not designed for concurrent multi-tab writes without external coordination.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Retrieve the document from the collection first using `find()` or `findOne()`, modify the retrieved object, and then pass that *same object* back to `collection.update()`. Alternatively, use `collection.findAndUpdate()` with a query and an update function.","message":"When updating documents, you must pass an existing document object (which contains the `$loki` ID) to the `collection.update()` method. Passing a plain object or a modified copy without the `$loki` property will result in a 'Trying to update unsynced document' error.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Always retrieve the document from the collection, modify the returned object reference, and then pass that specific object to `collection.update()`. Example: `const doc = collection.findOne({ id: 1 }); doc.field = 'newValue'; collection.update(doc);`","cause":"Attempting to update a document by passing a new object literal or a document missing the internal '$loki' ID.","error":"Trying to update unsynced document. Please save the document first by using insert() or addMany()"},{"fix":"For Node.js, ensure `const Loki = require('lokijs');` is used. For modern browsers or bundlers supporting ESM, use `import Loki from 'lokijs';`. If using a specific adapter, ensure the path `lokijs/src/loki-adapter-name` is correct. Verify `lokijs` is correctly installed in `node_modules` and your build process includes it.","cause":"Incorrect import path or CommonJS `require()` syntax in an environment where ESM is expected, or vice-versa, or bundling issues in environments like Electron.","error":"Error: Cannot find module 'lokijs'"}],"ecosystem":"npm"}