Fast document oriented javascript in-memory database
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Document storage and retrieval with powerful querying, indexing, and aggregation capabilities. Collections are the primary containers for documents in LokiJS.
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;
}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();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 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; }
);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');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');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');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);
}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 limitManage 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);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');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');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);
}
);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;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;
}