CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-lokijs

Fast document oriented javascript in-memory database

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

collection-operations.mddocs/

Collection Operations

Document storage and retrieval with powerful querying, indexing, and aggregation capabilities. Collections are the primary containers for documents in LokiJS.

Capabilities

Collection Constructor

Creates a new collection with optional configuration for indexing and behavior.

/**
 * Creates a new collection
 * @param name - Collection name
 * @param options - Collection configuration options
 */
constructor Collection(name: string, options?: CollectionOptions);

interface CollectionOptions {
  /** Array of field names that should be unique */
  unique?: string[];
  /** Array of field names for exact matching indexes */
  exact?: string[];
  /** Array of field names to create binary indexes on */
  indices?: string[];
  /** Enable adaptive binary indices */
  adaptiveBinaryIndices?: boolean;
  /** Enable async listeners */
  asyncListeners?: boolean;
  /** Disable meta properties ($loki, meta) */
  disableMeta?: boolean;
  /** Disable changes API tracking */
  disableChangesApi?: boolean;
  /** Disable delta changes API */
  disableDeltaChangesApi?: boolean;
  /** Enable auto-update for live objects */
  autoupdate?: boolean;
  /** Clone objects when retrieving */
  clone?: boolean;
  /** Clone method ('parse-stringify', 'jquery-extend-deep', 'shallow', 'shallow-assign') */
  cloneMethod?: string;
  /** Enable transactional mode */
  transactional?: boolean;
  /** Time to live in milliseconds */
  ttl?: number;
  /** TTL interval check in milliseconds */
  ttlInterval?: number;
}

Basic CRUD Operations

Fundamental create, read, update, and delete operations for documents.

/**
 * Insert one or more documents into the collection
 * @param doc - Document or array of documents to insert
 * @returns Inserted document(s) with generated $loki id
 */
insert(doc: object | object[]): object | object[];

/**
 * Update an existing document
 * @param doc - Document to update (must have $loki id)
 * @returns Updated document
 */
update(doc: object): object;

/**
 * Remove a document from the collection
 * @param doc - Document to remove (must have $loki id)
 * @returns Removed document
 */
remove(doc: object): object;

/**
 * Remove multiple documents in batch
 * @param batch - Array of documents to remove
 */
removeBatch(batch: object[]): void;

/**
 * Remove all documents matching query
 * @param query - Query object to match documents for removal
 */
removeWhere(query: object): void;

/**
 * Clear all documents from collection
 * @param options - Clear options
 */
clear(options?: object): void;

Usage Examples:

const users = db.addCollection('users');

// Insert single document
const user = users.insert({ name: 'Alice', age: 25, email: 'alice@example.com' });
console.log(user.$loki); // Auto-generated ID

// Insert multiple documents
const newUsers = users.insert([
  { name: 'Bob', age: 30, email: 'bob@example.com' },
  { name: 'Charlie', age: 35, email: 'charlie@example.com' }
]);

// Update document
user.age = 26;
users.update(user);

// Remove document
users.remove(user);

// Remove documents matching criteria
users.removeWhere({ age: { $lt: 30 } });

// Clear all documents
users.clear();

Querying Operations

Find and retrieve documents using various query methods.

/**
 * Find documents matching query criteria
 * @param query - Query object (empty object or undefined returns all)
 * @returns Array of matching documents
 */
find(query?: object): object[];

/**
 * Find first document matching query criteria
 * @param query - Query object
 * @returns First matching document or null
 */
findOne(query?: object): object | null;

/**
 * Get document by $loki id
 * @param id - Document $loki id
 * @param returnPosition - If true, return array index instead of document
 * @returns Document or index, or null if not found
 */
get(id: number, returnPosition?: boolean): object | number | null;

/**
 * Find document by indexed field value (fastest lookup)
 * @param field - Indexed field name
 * @param value - Field value to search for
 * @returns First matching document or null
 */
by(field: string, value: any): object | null;

/**
 * Filter documents using a custom function
 * @param fun - Filter function returning boolean
 * @returns Array of documents where function returns true
 */
where(fun: (obj: object) => boolean): object[];

Usage Examples:

// Find all active users
const activeUsers = users.find({ active: true });

// Find users over 25
const matureUsers = users.find({ age: { $gt: 25 } });

// Find first user named 'Alice'
const alice = users.findOne({ name: 'Alice' });

// Get document by ID
const user = users.get(5);

// Find by indexed field
const user = users.by('email', 'alice@example.com');

// Custom filter function
const youngActiveUsers = users.where(obj => obj.age < 30 && obj.active);

Advanced Finding

Advanced search capabilities including templates and compound operations.

/**
 * Find documents matching template object
 * @param template - Template object to match against
 * @returns Array of matching documents
 */
byExample(template: object): object[];

/**
 * Find single object matching template
 * @param template - Template object to match against
 * @returns First matching document or null
 */
findObject(template: object): object | null;

/**
 * Find multiple objects matching template
 * @param template - Template object to match against
 * @returns Array of matching documents
 */
findObjects(template: object): object[];

/**
 * Find documents and update them in one operation
 * @param filterObject - Query to find documents
 * @param updateFunction - Function to update each document
 * @returns Array of updated documents
 */
findAndUpdate(filterObject: object, updateFunction: (obj: object) => void): object[];

/**
 * Find documents and remove them in one operation
 * @param filterObject - Query to find documents
 * @returns Array of removed documents
 */
findAndRemove(filterObject: object): object[];

/**
 * Update documents matching filter function
 * @param filterFunction - Function to identify documents to update
 * @param updateFunction - Function to update each document
 */
updateWhere(filterFunction: (obj: object) => boolean, updateFunction: (obj: object) => void): void;

Usage Examples:

// Find by example template
const users = users.byExample({ active: true, department: 'Engineering' });

// Find and update in one operation
const updated = users.findAndUpdate(
  { active: false },
  (obj) => { obj.lastLogin = new Date(); }
);

// Find and remove inactive users
const removed = users.findAndRemove({ active: false });

// Update where function matches
users.updateWhere(
  obj => obj.age > 65,
  obj => { obj.retired = true; }
);

Counting and Statistics

Count documents and calculate statistical values across the collection.

/**
 * Count documents in collection
 * @param query - Optional query to filter documents
 * @returns Number of matching documents
 */
count(query?: object): number;

/**
 * Get maximum value of a field
 * @param field - Field name to find maximum value
 * @returns Maximum value
 */
max(field: string): any;

/**
 * Get minimum value of a field
 * @param field - Field name to find minimum value
 * @returns Minimum value
 */
min(field: string): any;

/**
 * Get record with maximum field value
 * @param field - Field name to compare
 * @returns Document with maximum field value
 */
maxRecord(field: string): object;

/**
 * Get record with minimum field value
 * @param field - Field name to compare
 * @returns Document with minimum field value
 */
minRecord(field: string): object;

/**
 * Calculate average of field values
 * @param field - Field name to average
 * @returns Average value
 */
avg(field: string): number;

/**
 * Calculate standard deviation of field values
 * @param field - Field name to calculate standard deviation
 * @returns Standard deviation
 */
stdDev(field: string): number;

/**
 * Find most frequent value in field
 * @param field - Field name to analyze
 * @returns Most frequent value
 */
mode(field: string): any;

/**
 * Calculate median value of field
 * @param field - Field name to calculate median
 * @returns Median value
 */
median(field: string): number;

Usage Examples:

// Count all users
const totalUsers = users.count();

// Count active users
const activeCount = users.count({ active: true });

// Statistical operations
const maxAge = users.max('age');
const minAge = users.min('age');
const avgAge = users.avg('age');
const oldestUser = users.maxRecord('age');

// Distribution analysis
const commonDepartment = users.mode('department');
const medianSalary = users.median('salary');

Indexing Operations

Manage indexes for improved query performance.

/**
 * Ensure binary index exists on property
 * @param property - Property name to index
 * @param force - Force index rebuild
 */
ensureIndex(property: string, force?: boolean): void;

/**
 * Ensure unique index exists on field
 * @param field - Field name for unique index
 */
ensureUniqueIndex(field: string): void;

/**
 * Ensure all configured indexes exist
 * @param force - Force rebuild of all indexes
 */
ensureAllIndexes(force?: boolean): void;

/**
 * Check and optionally rebuild specific index
 * @param property - Property name to check
 * @param options - Check options
 */
checkIndex(property: string, options?: object): void;

/**
 * Check and optionally rebuild all indexes
 * @param options - Check options
 */
checkAllIndexes(options?: object): void;

/**
 * Get values from binary index
 * @param property - Indexed property name
 * @returns Array of indexed values
 */
getBinaryIndexValues(property: string): any[];

Usage Examples:

// Create collection with indexes
const users = db.addCollection('users', {
  unique: ['email'],
  indices: ['age', 'department']
});

// Add index later
users.ensureIndex('lastName');

// Check if indexes need rebuilding
users.checkAllIndexes();

// Get indexed values
const departments = users.getBinaryIndexValues('department');

Transform Operations

Manage named transform pipelines for reusable query operations.

/**
 * Add a named transform to the collection
 * @param name - Transform name
 * @param transform - Array of transform steps
 */
addTransform(name: string, transform: any[]): void;

/**
 * Get a named transform by name
 * @param name - Transform name
 * @returns Transform array or null if not found
 */
getTransform(name: string): any[] | null;

/**
 * Update an existing named transform
 * @param name - Transform name
 * @param transform - New transform steps
 */
setTransform(name: string, transform: any[]): void;

/**
 * Remove a named transform
 * @param name - Transform name
 */
removeTransform(name: string): void;

Usage Examples:

// Define a reusable transform
users.addTransform('activeUsers', [
  { type: 'find', value: { active: true } },
  { type: 'simplesort', property: 'name' }
]);

// Use the transform
const result = users.chain('activeUsers').data();

// Update transform
users.setTransform('activeUsers', [
  { type: 'find', value: { active: true, verified: true } },
  { type: 'simplesort', property: 'name' }
]);

// Remove transform
users.removeTransform('activeUsers');

Transaction Support

Transactional operations for consistent data modifications.

/**
 * Start a transaction on the collection
 * @returns Collection instance for chaining
 */
startTransaction(): Collection;

/**
 * Commit the current transaction
 * @returns Collection instance for chaining
 */
commit(): Collection;

/**
 * Rollback the current transaction
 * @returns Collection instance for chaining
 */
rollback(): Collection;

Usage Examples:

// Start transaction
users.startTransaction();

try {
  // Perform multiple operations
  users.insert({ name: 'Alice', age: 25 });
  users.insert({ name: 'Bob', age: 30 });
  
  // Update existing records
  const activeUsers = users.find({ active: true });
  activeUsers.forEach(user => {
    user.lastUpdated = new Date();
    users.update(user);
  });
  
  // Commit changes
  users.commit();
  console.log('Transaction committed successfully');
} catch (error) {
  // Rollback on error
  users.rollback();
  console.error('Transaction rolled back:', error);
}

TTL (Time To Live) Configuration

Configure automatic document expiration based on age.

/**
 * Set TTL (Time To Live) for documents in collection
 * @param age - Maximum age in milliseconds
 * @param interval - Check interval in milliseconds
 */
setTTL(age: number, interval?: number): void;

Usage Examples:

// Set TTL when creating collection
const sessions = db.addCollection('sessions', {
  ttl: 24 * 60 * 60 * 1000,      // 24 hours
  ttlInterval: 60 * 1000         // Check every minute
});

// Or set TTL later
sessions.setTTL(
  30 * 60 * 1000,  // 30 minutes
  5 * 60 * 1000    // Check every 5 minutes
);

// Documents will be automatically removed when they exceed the age limit

Auto-Update Observers

Manage automatic updates for live objects.

/**
 * Add auto-update observer for an object
 * @param object - Object to observe for changes
 */
addAutoUpdateObserver(object: object): void;

/**
 * Remove auto-update observer for an object
 * @param object - Object to stop observing
 */
removeAutoUpdateObserver(object: object): void;

Usage Examples:

// Enable auto-update for collection
const users = db.addCollection('users', {
  autoupdate: true
});

// Insert document
const user = users.insert({ name: 'Alice', age: 25 });

// Modify the object directly - changes will be automatically saved
user.age = 26;  // Collection automatically updated

// Manually manage observers
users.addAutoUpdateObserver(user);
users.removeAutoUpdateObserver(user);

Staging Operations

Stage and commit changes in batches.

/**
 * Stage an object for later commit
 * @param stageName - Name of the stage
 * @param obj - Object to stage
 */
stage(stageName: string, obj: object): void;

/**
 * Get staged objects by stage name
 * @param name - Stage name
 * @returns Array of staged objects
 */
getStage(name: string): object[];

/**
 * Commit staged changes
 * @param stageName - Name of stage to commit
 * @param message - Optional commit message
 */
commitStage(stageName: string, message?: string): void;

Usage Examples:

// Stage multiple changes
users.stage('batch1', { name: 'Alice', age: 25 });
users.stage('batch1', { name: 'Bob', age: 30 });
users.stage('batch1', { name: 'Charlie', age: 35 });

// Review staged changes
const staged = users.getStage('batch1');
console.log('Staged documents:', staged.length);

// Commit the stage
users.commitStage('batch1', 'Added new users batch');

Advanced Operations

Specialized operations for complex data manipulation and analysis.

/**
 * Create a chainable resultset for complex operations
 * @param transform - Transform name to apply
 * @param parameters - Transform parameters
 * @returns Resultset for chaining operations
 */
chain(transform?: string, parameters?: object): Resultset;

/**
 * Extract unique values from a field
 * @param field - Field name to extract values from
 * @returns Array of unique values
 */
extract(field: string): any[];

/**
 * Perform map-reduce operation on collection
 * @param mapFunction - Map function to apply to each document
 * @param reduceFunction - Reduce function to combine results
 * @returns Reduced result
 */
mapReduce(mapFunction: (obj: object) => any, reduceFunction: (array: any[]) => any): any;

/**
 * Perform equi-join with external data
 * @param joinData - External data to join with
 * @param leftJoinProp - Property from collection documents
 * @param rightJoinProp - Property from external data
 * @param mapFun - Optional function to transform join results
 * @param dataOptions - Additional options
 * @returns Array of joined results
 */
eqJoin(joinData: any[], leftJoinProp: string, rightJoinProp: string, mapFun?: Function, dataOptions?: object): object[];

Usage Examples:

// Chain complex operations
const result = users.chain()
  .find({ active: true })
  .where(obj => obj.age > 25)
  .simplesort('name')
  .limit(10)
  .data();

// Extract unique departments
const departments = users.extract('department');

// Map-reduce to calculate department sizes
const deptSizes = users.mapReduce(
  obj => ({ [obj.department]: 1 }),
  results => {
    const counts = {};
    results.forEach(result => {
      Object.keys(result).forEach(dept => {
        counts[dept] = (counts[dept] || 0) + result[dept];
      });
    });
    return counts;
  }
);

// Join with external data
const orders = [
  { userId: 1, total: 100 },
  { userId: 2, total: 200 }
];
const usersWithOrders = users.eqJoin(orders, 'id', 'userId');

Async Operations

Perform asynchronous operations on collections.

/**
 * Execute function asynchronously on collection
 * @param fun - Function to execute
 * @param callback - Completion callback
 */
async(fun: Function, callback: Function): void;

Usage Examples:

// Async operation example
users.async(
  function(collection) {
    // Perform heavy operation
    return collection.find({ department: 'Engineering' })
      .map(user => ({ ...user, processed: true }));
  },
  function(result) {
    console.log('Async operation completed:', result.length);
  }
);

Internal Methods

Low-level methods for advanced usage and debugging.

/**
 * Ensure collection has sequential IDs without gaps
 */
ensureId(): void;

/**
 * Asynchronous version of ensureId
 * @param callback - Completion callback
 */
ensureIdAsync(callback: Function): void;

/**
 * Configure collection options after creation
 * @param options - Configuration options
 */
configureOptions(options: CollectionOptions): void;

/**
 * Get binary index position for a data position
 * @param dataPosition - Position in data array
 * @param binaryIndexName - Name of binary index
 * @returns Index position
 */
getBinaryIndexPosition(dataPosition: number, binaryIndexName: string): number;

/**
 * Calculate range start for binary index searches
 * @param prop - Property name
 * @param val - Search value
 * @param adaptive - Whether to use adaptive indices
 * @param usingDotNotation - Whether using dot notation
 * @returns Range start position
 */
calculateRangeStart(prop: string, val: any, adaptive?: boolean, usingDotNotation?: boolean): number;

/**
 * Calculate range end for binary index searches
 * @param prop - Property name
 * @param val - Search value
 * @param usingDotNotation - Whether using dot notation
 * @returns Range end position
 */
calculateRangeEnd(prop: string, val: any, usingDotNotation?: boolean): number;

/**
 * No-operation function for testing/debugging
 */
no_op(): void;

Properties

interface Collection {
  /** Collection name */
  name: string;
  /** Array of documents */
  data: object[];
  /** Collection configuration options */
  options: CollectionOptions;
  /** Binary indices for optimized querying */
  binaryIndices: { [field: string]: any };
  /** Unique field constraints */
  constraints: { unique: { [field: string]: any } };
  /** Array of dynamic views */
  DynamicViews: DynamicView[];
  /** Transform functions */
  transforms: { [name: string]: any[] };
  /** Maximum $loki id assigned */
  maxId: number;
  /** Dirty flag indicating unsaved changes */
  dirty: boolean;
}

docs

advanced-querying.md

collection-operations.md

database-management.md

dynamic-views.md

index.md

persistence-adapters.md

tile.json