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

advanced-querying.mddocs/

Advanced Querying

Chainable query interface with filtering, sorting, transformations, and aggregation operations using the Resultset class for complex data operations.

Capabilities

Resultset Constructor

Creates a chainable query interface from a collection for complex operations.

/**
 * Creates a new resultset for chainable operations
 * @param collection - Source collection
 * @param options - Resultset options
 */
constructor Resultset(collection: Collection, options?: object);

Usage Examples:

// Create resultset from collection
const users = db.getCollection('users');
const resultset = new users.constructor.Resultset(users);

// Or create via collection.chain()
const resultset = users.chain();

Query Operations

Filter documents using various query criteria and logical operations.

/**
 * Apply find query to filter documents
 * @param query - MongoDB-style query object
 * @param firstOnly - If true, stop after first match
 * @returns Resultset for chaining
 */
find(query: object, firstOnly?: boolean): Resultset;

/**
 * Apply OR query across multiple expressions
 * @param expressionArray - Array of query expressions
 * @returns Resultset for chaining
 */
findOr(expressionArray: object[]): Resultset;

/**
 * Apply AND query across multiple expressions
 * @param expressionArray - Array of query expressions
 * @returns Resultset for chaining
 */
findAnd(expressionArray: object[]): Resultset;

/**
 * Filter using custom function
 * @param fun - Filter function returning boolean
 * @returns Resultset for chaining
 */
where(fun: (obj: object) => boolean): Resultset;

Usage Examples:

// Basic find operations
const activeUsers = users.chain()
  .find({ active: true })
  .data();

// OR query
const result = users.chain()
  .findOr([
    { department: 'Engineering' },
    { department: 'Design' },
    { age: { $gt: 50 } }
  ])
  .data();

// AND query
const result = users.chain()
  .findAnd([
    { active: true },
    { age: { $gte: 25 } },
    { department: { $ne: 'Intern' } }
  ])
  .data();

// Custom filter function
const result = users.chain()
  .where(obj => obj.email.includes('@company.com'))
  .data();

Sorting Operations

Sort resultset data using various criteria and custom comparison functions.

/**
 * Sort using custom comparison function
 * @param comparefun - Function returning -1, 0, or 1 for comparison
 * @returns Resultset for chaining
 */
sort(comparefun: (a: object, b: object) => number): Resultset;

/**
 * Simple sort by property name
 * @param propname - Property name to sort by
 * @param options - Sort options (desc: boolean)
 * @returns Resultset for chaining
 */
simplesort(propname: string, options?: { desc?: boolean }): Resultset;

/**
 * Sort by multiple properties with individual sort directions
 * @param properties - Array of [property, isDescending] pairs
 * @returns Resultset for chaining
 */
compoundsort(properties: [string, boolean][]): Resultset;

Usage Examples:

// Simple ascending sort
const result = users.chain()
  .find({ active: true })
  .simplesort('name')
  .data();

// Simple descending sort
const result = users.chain()
  .find({ active: true })
  .simplesort('age', { desc: true })
  .data();

// Compound sort
const result = users.chain()
  .find({ active: true })
  .compoundsort([
    ['department', false],  // ascending
    ['age', true]          // descending
  ])
  .data();

// Custom sort function
const result = users.chain()
  .find({ active: true })
  .sort((a, b) => {
    // Sort by name length, then alphabetically
    if (a.name.length !== b.name.length) {
      return a.name.length - b.name.length;
    }
    return a.name.localeCompare(b.name);
  })
  .data();

Pagination Operations

Limit and offset results for pagination and data chunking.

/**
 * Limit number of results returned
 * @param qty - Maximum number of results
 * @returns Resultset for chaining
 */
limit(qty: number): Resultset;

/**
 * Skip specified number of results
 * @param pos - Number of results to skip
 * @returns Resultset for chaining
 */
offset(pos: number): Resultset;

Usage Examples:

// Get first 10 users
const firstPage = users.chain()
  .find({ active: true })
  .limit(10)
  .data();

// Get users 11-20 (second page)
const secondPage = users.chain()
  .find({ active: true })
  .offset(10)
  .limit(10)
  .data();

// Get top 5 highest paid employees
const topEarners = users.chain()
  .find({ active: true })
  .simplesort('salary', { desc: true })
  .limit(5)
  .data();

Data Retrieval

Retrieve the final results from the query chain.

/**
 * Execute the query chain and return results
 * @param options - Data retrieval options
 * @returns Array of documents matching the query chain
 */
data(options?: { removeMeta?: boolean, forceClones?: boolean }): object[];

/**
 * Get count of documents in resultset without retrieving data
 * @returns Number of documents that would be returned
 */
count(): number;

Usage Examples:

// Get results with metadata
const results = users.chain()
  .find({ active: true })
  .simplesort('name')
  .data();

// Get results without metadata
const cleanResults = users.chain()
  .find({ active: true })
  .data({ removeMeta: true });

// Just get the count
const activeCount = users.chain()
  .find({ active: true })
  .count();

Transformation Operations

Apply transformations and modifications to query results.

/**
 * Apply a transform to the resultset
 * @param transform - Transform name or function
 * @param parameters - Transform parameters
 * @returns Resultset for chaining
 */
transform(transform: string | Function, parameters?: object): Resultset;

/**
 * Update documents in the resultset
 * @param updateFunction - Function to update each document
 * @returns Resultset for chaining
 */
update(updateFunction: (obj: object) => void): object[];

/**
 * Remove documents in the resultset from the collection
 * @returns Array of removed documents
 */
remove(): object[];

/**
 * Copy the resultset
 * @returns New resultset with same filters
 */
copy(): Resultset;

/**
 * Reset resultset to include all documents
 * @returns Resultset for chaining
 */
reset(): Resultset;

/**
 * Create a branch (copy) of the resultset
 * @returns New resultset with same filters
 */
branch(): Resultset;

/**
 * Serialize resultset to JSON
 * @returns JSON representation of the resultset
 */
toJSON(): string;

Usage Examples:

// Apply transform
const transformed = users.chain()
  .find({ active: true })
  .transform('extractName')  // Assuming transform exists
  .data();

// Update documents in resultset
const updated = users.chain()
  .find({ department: 'Engineering' })
  .update(obj => {
    obj.lastReviewDate = new Date();
    obj.needsReview = false;
  });

// Remove documents matching criteria
const removed = users.chain()
  .find({ active: false, lastLogin: { $lt: new Date('2020-01-01') } })
  .remove();

// Copy resultset for different operations
const baseQuery = users.chain().find({ active: true });
const engineers = baseQuery.copy().find({ department: 'Engineering' }).data();
const designers = baseQuery.copy().find({ department: 'Design' }).data();

Aggregation Operations

Perform aggregation and join operations on query results.

/**
 * Perform map-reduce operation on resultset
 * @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 leftJoinKey - Property from resultset documents
 * @param rightJoinKey - Property from external data
 * @param mapFun - Optional function to transform join results
 * @param dataOptions - Additional options
 * @returns Array of joined results
 */
eqJoin(joinData: any[], leftJoinKey: string, rightJoinKey: string, mapFun?: Function, dataOptions?: object): object[];

/**
 * Apply map operation to transform each document
 * @param mapFun - Map function to apply
 * @param dataOptions - Additional options
 * @returns Array of transformed results
 */
map(mapFun: (obj: object) => any, dataOptions?: object): any[];

Usage Examples:

// Map-reduce to calculate department statistics
const deptStats = users.chain()
  .find({ active: true })
  .mapReduce(
    obj => ({ [obj.department]: { count: 1, totalSalary: obj.salary } }),
    results => {
      const stats = {};
      results.forEach(result => {
        Object.keys(result).forEach(dept => {
          if (!stats[dept]) {
            stats[dept] = { count: 0, totalSalary: 0 };
          }
          stats[dept].count += result[dept].count;
          stats[dept].totalSalary += result[dept].totalSalary;
        });
      });
      // Calculate averages
      Object.keys(stats).forEach(dept => {
        stats[dept].avgSalary = stats[dept].totalSalary / stats[dept].count;
      });
      return stats;
    }
  );

// Join with external orders data
const orders = [
  { customerId: 1, total: 150.00, date: '2023-01-15' },
  { customerId: 2, total: 75.50, date: '2023-01-16' }
];

const usersWithOrders = users.chain()
  .find({ active: true })
  .eqJoin(orders, 'id', 'customerId', (left, right) => ({
    user: left,
    orderTotal: right.total,
    orderDate: right.date
  }));

// Map to extract specific fields
const userSummaries = users.chain()
  .find({ active: true })
  .map(obj => ({
    name: obj.name,
    email: obj.email,
    department: obj.department
  }));

Query Operators

LokiJS supports MongoDB-style query operators for complex filtering:

// Comparison operators
$eq: any;           // Strict equality
$aeq: any;          // Abstract equality (==)
$ne: any;           // Not equal
$gt: any;           // Greater than
$gte: any;          // Greater than or equal
$lt: any;           // Less than
$lte: any;          // Less than or equal

// Array operators
$in: any[];         // Value in array
$nin: any[];        // Value not in array
$contains: any;     // Array contains value
$containsAny: any[]; // Array contains any of values
$containsNone: any[]; // Array contains none of values

// Object operators
$exists: boolean;   // Property exists
$type: string;      // Type checking ('string', 'number', etc.)
$size: number;      // Array/object size
$regex: RegExp;     // Regular expression match

// Logical operators
$and: object[];     // Logical AND
$or: object[];      // Logical OR
$not: object;       // Logical NOT

// Numeric operators
$between: [any, any]; // Between two values
$finite: boolean;   // Is finite number

// Advanced operators
$dteq: any;           // Date/abstract equality
$jgt: any;            // JavaScript greater than (lightweight)
$jgte: any;           // JavaScript greater than or equal
$jlt: any;            // JavaScript less than (lightweight)
$jlte: any;           // JavaScript less than or equal
$jbetween: [any, any]; // JavaScript between (lightweight)
$inSet: Set<any>;     // Value in Set object
$keyin: object;       // Property key exists in object
$nkeyin: object;      // Property key does not exist in object
$definedin: object;   // Property is defined in object (not undefined)
$undefinedin: object; // Property is undefined in object
$containsString: string; // String contains substring
$elemMatch: object;   // Array element matches query

// Custom operators
$where: Function;     // Custom function filter

Usage Examples:

// Comparison operators
const adults = users.chain().find({ age: { $gte: 18 } }).data();
const active = users.chain().find({ status: { $ne: 'inactive' } }).data();

// Array operators
const managers = users.chain().find({ 
  roles: { $contains: 'manager' } 
}).data();

const techRoles = users.chain().find({
  skills: { $containsAny: ['JavaScript', 'Python', 'Java'] }
}).data();

// Object operators
const hasPhone = users.chain().find({ 
  phone: { $exists: true } 
}).data();

const numbers = users.chain().find({ 
  employeeId: { $type: 'number' } 
}).data();

// Logical operators
const seniorEngineers = users.chain().find({
  $and: [
    { department: 'Engineering' },
    { experience: { $gte: 5 } },
    { level: { $in: ['Senior', 'Lead', 'Principal'] } }
  ]
}).data();

// Custom function filter
const recentHires = users.chain().find({
  $where: function(obj) {
    const hireDate = new Date(obj.hireDate);
    const sixMonthsAgo = new Date();
    sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6);
    return hireDate > sixMonthsAgo;
  }
}).data();

// Advanced operators
const advancedUsers = users.chain().find({
  // Date equality
  createdAt: { $dteq: new Date('2023-01-01') },
  
  // Lightweight JavaScript comparisons
  score: { $jgt: 85 },
  
  // Between range (lightweight)
  age: { $jbetween: [25, 65] },
  
  // Set membership
  department: { $inSet: new Set(['Engineering', 'Design']) },
  
  // Object property checks
  userId: { $keyin: userMap },
  preferences: { $definedin: { theme: 'dark' } },
  
  // String operations
  email: { $containsString: '@company.com' },
  
  // Array element matching
  orders: {
    $elemMatch: {
      status: 'completed',
      total: { $gt: 100 }
    }
  }
}).data();

Additional Query Examples

Advanced query patterns using the extended operator set.

// Complex nested queries
const complexResults = users.chain()
  .find({
    $and: [
      { status: 'active' },
      { 
        $or: [
          { department: { $inSet: new Set(['Engineering', 'Design']) } },
          { skills: { $containsAny: ['leadership', 'management'] } }
        ]
      },
      {
        projects: {
          $elemMatch: {
            status: 'completed',
            budget: { $jbetween: [10000, 100000] },
            deadline: { $dteq: new Date('2023-12-31') }
          }
        }
      }
    ]
  })
  .data();

// String and object operations
const textSearchResults = users.chain()
  .find({
    // String contains
    biography: { $containsString: 'engineer' },
    
    // Property existence
    permissions: { $definedin: { admin: true } },
    
    // Key membership  
    userId: { $keyin: { 1: true, 2: true, 3: true } },
    
    // Undefined check
    deletedAt: { $undefinedin: {} }
  })
  .data();

Resultset Aliases

Alternative method names for MongoDB compatibility.

// Logical operator aliases
$or(expressionArray: object[]): Resultset;  // Alias for findOr
$and(expressionArray: object[]): Resultset; // Alias for findAnd

Usage Examples:

// Use MongoDB-style operator aliases
const result1 = users.chain()
  .$or([
    { department: 'Engineering' },
    { department: 'Design' }
  ])
  .data();

const result2 = users.chain()
  .$and([
    { active: true },
    { age: { $gte: 25 } }
  ])
  .data();

Properties

interface Resultset {
  /** Reference to source collection */
  collection: Collection;
  /** Array of filtered row indices */
  filteredrows: number[];
  /** Filter initialization flag */
  filterInitialized: boolean;
}

docs

advanced-querying.md

collection-operations.md

database-management.md

dynamic-views.md

index.md

persistence-adapters.md

tile.json