LokiJS: In-Memory Document Database

1.5.11 · abandoned · verified Wed Apr 22

LokiJS is a fast, embeddable, document-oriented NoSQL database written entirely in JavaScript. It operates in-memory, making it suitable for performance-critical applications like client-side session stores, embedded databases in Electron or Node-WebKit apps, or mobile applications using frameworks like Nativescript and Cordova. It features collections with unique and binary indexes, dynamic views, a Changes API for synchronization, and supports joins. Persistence is handled through a pluggable adapter system, with built-in adapters for Node.js file system, browser IndexedDB, and localStorage. While the last published version on npm is 1.5.12 (last updated around 2019-2020), the project has seen minimal activity and is largely considered unmaintained, with its official successor being LokiDB. Users should be aware of its unmaintained status and consider the successor or other alternatives for new projects.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart initializes a LokiJS database with IndexedDB persistence, creates a collection, inserts and updates documents, and demonstrates a basic query. It highlights asynchronous database loading/saving and explicit updates.

const Loki = require('lokijs');
const LokiIndexedAdapter = require('lokijs/src/loki-indexed-adapter');

async function initializeDatabase() {
  const adapter = new LokiIndexedAdapter('my-loki-app');
  const db = new Loki('my-database.db', {
    adapter: adapter,
    autosave: true,
    autosaveInterval: 4000 // Save every 4 seconds
  });

  // Load the database from persistence, or create if it doesn't exist
  await new Promise((resolve, reject) => {
    db.loadDatabase({}, (err) => {
      if (err) {
        console.error('Error loading database:', err);
        reject(err);
      } else {
        console.log('Database loaded or created.');
        resolve();
      }
    });
  });

  let users = db.getCollection('users');
  if (!users) {
    users = db.addCollection('users', { unique: ['email'], autoupdate: true });
    console.log('"users" collection created.');
  }

  // Insert some data if the collection is empty
  if (users.count() === 0) {
    users.insert({ name: 'Alice', email: 'alice@example.com', age: 30 });
    users.insert({ name: 'Bob', email: 'bob@example.com', age: 24 });
    users.insert({ name: 'Charlie', email: 'charlie@example.com', age: 35 });
    console.log('Initial data inserted.');
  }

  // Find and update a document
  let bob = users.findOne({ name: 'Bob' });
  if (bob) {
    bob.age = 25;
    users.update(bob); // Explicit update might be needed for certain changes like array mutations
    console.log('Bob updated:', users.findOne({ name: 'Bob' }));
  }

  // Query data
  const youngUsers = users.find({ age: { '$lt': 30 } });
  console.log('Users under 30:', youngUsers);

  // Save changes explicitly (autosave also does this)
  await new Promise((resolve, reject) => {
    db.saveDatabase((err) => {
      if (err) reject(err); else resolve();
    });
  });
  console.log('Database saved.');

  return db;
}

initializeDatabase().catch(console.error);

view raw JSON →