npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

mongo-bolt

v1.0.5

Published

A lightweight, beginner-friendly MongoDB wrapper with inbuilt caching and simplified joins/indexing.

Downloads

22

Readme

Mongo-Bolt

Mongo-Bolt is a lightweight, modern MongoDB wrapper built on top of Mongoose, designed to simplify database operations with an intuitive, beginner-friendly API. It provides robust tools for connecting to MongoDB, managing collections, performing CRUD operations, handling transactions, building aggregation pipelines, and managing indexes. With inbuilt caching, simplified joins, and streamlined indexing, Mongo-Bolt is ideal for Node.js developers building efficient and scalable applications.

Inspired by the clarity and interactivity of Docs by Hashnode, this documentation offers a modular, developer-centric guide to Mongo-Bolt. The AggregationBuilder class simplifies MongoDB’s complex aggregation pipelines, making them accessible to beginners and powerful for advanced users. Whether you're new to MongoDB or an experienced developer, Mongo-Bolt empowers you to work with MongoDB efficiently.

Why Mongo-Bolt?

Mongo-Bolt stands out with features tailored to enhance developer experience and performance:

  • Beginner-Friendly: Intuitive method names, clear error messages, and a streamlined API reduce the learning curve for MongoDB.
  • Inbuilt Caching: Improves performance for repeated queries by caching results (implementation details to be covered in a forthcoming blog).
  • Simplified Joins, Indexing, and Multi-Collection Fetching: Methods like findAndPopulateById, findAndPopulateByKey, and index management make complex operations straightforward.

Table of Contents

Installation

Install Mongo-Bolt via npm:

npm install mongo-bolt

Mongo-Bolt requires Mongoose as a peer dependency. Install it if not already present:

npm install mongoose

Getting Started

To start using Mongo-Bolt, import the MongoDB class, configure your MongoDB connection, and connect to your database:

import MongoDB from 'mongo-bolt';

const config = {
  uri: 'mongodb://localhost:27017/mydb',
  options: {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  },
};

const db = new MongoDB(config);

async function init() {
  try {
    await db.connect();
    console.log('Connected to MongoDB');
  } catch (error) {
    console.error('Connection failed:', error.message);
  }
}

init();

This example showcases Mongo-Bolt’s beginner-friendly setup, inspired by Hashnode Docs’ intuitive onboarding.

Configuration

The MongoDB constructor accepts a config object with the following properties:

| Property | Type | Description | Required | |-----------|----------|-----------------------------------------------------------------------------|----------| | uri | string | MongoDB connection URI (e.g., mongodb://localhost:27017/mydb) | Yes | | options | object | Mongoose connection options (e.g., { useNewUrlParser: true }) | No |

Example:

const config = {
  uri: 'mongodb://localhost:27017/mydb',
  options: {
    useNewUrlParser: true,
    useUnifiedTopology: true,
    serverSelectionTimeoutMS: 5000,
  },
};

Methods

Mongo-Bolt provides two primary interfaces: the MongoDB class for core database operations and the AggregationBuilder class for constructing aggregation pipelines. Each method is documented with its signature, parameters, return value, and an example, ensuring clarity and interactivity akin to Hashnode Docs.

MongoDB Class Methods

connect

Establishes a connection to the MongoDB database.

Signature:

async connect(): Promise<void>

Returns:

  • Promise<void>: Resolves when the connection is successful, or rejects with an error.

Example:

const db = new MongoDB(config);
await db.connect();
console.log('Database connected');

createStore

Creates a new collection with a specified schema.

Signature:

async createStore<T>(
  collectionName: string,
  schema: SchemaDefinition<SchemaDefinitionType<T>>
): Promise<void>

Parameters:

| Parameter | Type | Description | Required | |------------------|-----------------------------------|-------------------------------------------------------------------|----------| | collectionName | string | Name of the collection to create. | Yes | | schema | SchemaDefinition<SchemaDefinitionType<T>> | Mongoose schema definition for the collection. | Yes |

Returns:

  • Promise<void>: Resolves when the collection is created, or rejects with an error.

Example:

import { Schema } from 'mongoose';

const userSchema = {
  name: { type: String, required: true },
  email: { type: String, required: true, unique: true },
};

const db = new MongoDB(config);
await db.connect();
await db.createStore('users', userSchema);
console.log('Users collection created');

insertItem

Inserts a single document into a collection.

Signature:

async insertItem<T>(collectionName: string, documentData: T): Promise<void>

Parameters:

| Parameter | Type | Description | Required | |------------------|----------|----------------------------------------------------------|----------| | collectionName | string | Name of the collection to insert into. | Yes | | documentData | T | The document data to insert. | Yes |

Returns:

  • Promise<void>: Resolves when the document is inserted, or rejects with an error.

Example:

const user = {
  name: 'John Doe',
  email: '[email protected]',
};

await db.insertItem('users', user);
console.log('User inserted');

insertItems

Inserts multiple documents into a collection.

Signature:

async insertItems<T>(collectionName: string, documentsData: T[]): Promise<void>

Parameters:

| Parameter | Type | Description | Required | |------------------|----------|----------------------------------------------------------|----------| | collectionName | string | Name of the collection to insert into. | Yes | | documentsData | T[] | Array of document data to insert. | Yes |

Returns:

  • Promise<void>: Resolves when all documents are inserted, or rejects with an error.

Example:

const users = [
  { name: 'Jane Doe', email: '[email protected]' },
  { name: 'Bob Smith', email: '[email protected]' },
];

await db.insertItems('users', users);
console.log('Users inserted');

findItem

Retrieves documents from a collection based on a query.

Signature:

async findItem<T>(
  collectionName: string,
  query: Record<string, any> = {}
): Promise<T[]>

Parameters:

| Parameter | Type | Description | Required | |------------------|-------------------------|----------------------------------------------------------|----------| | collectionName | string | Name of the collection to query. | Yes | | query | Record<string, any> | Query object to filter documents (default: {}). | No |

Returns:

  • Promise<T[]>: An array of documents matching the query.

Example:

const users = await db.findItem('users', { name: 'John Doe' });
console.log(users); // [{ name: 'John Doe', email: '[email protected]', ... }]

updateItems

Updates multiple documents in a collection based on a query.

Signature:

async updateItems(
  collectionName: string,
  query: Record<string, any>,
  update: Record<string, any>
): Promise<number>

Parameters:

| Parameter | Type | Description | Required | |------------------|-------------------------|----------------------------------------------------------|----------| | collectionName | string | Name of the collection to update. | Yes | | query | Record<string, any> | Query to select documents to update. | Yes | | update | Record<string, any> | Update operations to apply (e.g., { $set: { ... } }). | Yes |

Returns:

  • Promise<number>: The number of documents updated.

Example:

const updatedCount = await db.updateItems(
  'users',
  { name: 'John Doe' },
  { $set: { email: '[email protected]' } }
);
console.log(`${updatedCount} users updated`);

deleteStore

Deletes a collection from the database.

Signature:

async deleteStore(collectionName: string): Promise<void>

Parameters:

| Parameter | Type | Description | Required | |------------------|----------|----------------------------------------------------------|----------| | collectionName | string | Name of the collection to delete. | Yes |

Returns:

  • Promise<void>: Resolves when the collection is deleted, or rejects with an error.

Example:

await db.deleteStore('users');
console.log('Users collection deleted');

dropItem

Deletes a single document from a collection based on a query.

Signature:

async dropItem(
  storeName: string,
  itemInfo: Record<string, any>
): Promise<void>

Parameters:

| Parameter | Type | Description | Required | |--------------|-------------------------|----------------------------------------------------------|----------| | storeName | string | Name of the collection to delete from. | Yes | | itemInfo | Record<string, any> | Query to identify the document to delete. | Yes |

Returns:

  • Promise<void>: Resolves when the document is deleted, or rejects with an error.

Example:

await db.dropItem('users', { email: '[email protected]' });
console.log('User dropped');

dropItems

Deletes multiple documents from a collection based on a query.

Signature:

async dropItems(
  storeName: string,
  itemInfo: Record<string, any>
): Promise<void>

Parameters:

| Parameter | Type | Description | Required | |--------------|-------------------------|----------------------------------------------------------|----------| | storeName | string | Name of the collection to delete from. | Yes | | itemInfo | Record<string, any> | Query to identify documents to delete. | Yes |

Returns:

  • Promise<void>: Resolves when the documents are deleted, or rejects with an error.

Example:

await db.dropItems('users', { name: 'John Doe' });
console.log('Users dropped');

truncateStore

Removes all documents from a collection without deleting the collection itself.

Signature:

async truncateStore(storeName: string): Promise<void>

Parameters:

| Parameter | Type | Description | Required | |--------------|----------|----------------------------------------------------------|----------| | storeName | string | Name of the collection to truncate. | Yes |

Returns:

  • Promise<void>: Resolves when the collection is truncated, or rejects with an error.

Example:

await db.truncateStore('users');
console.log('Users collection truncated');

alterStore

Modifies the schema of an existing collection and updates documents as needed.

Signature:

async alterStore<T, U>(
  storeName: string,
  newSchema: SchemaDefinition<SchemaDefinitionType<U>>,
  changeValues: Record<string, any>
): Promise<void>

Parameters:

| Parameter | Type | Description | Required | |----------------|-----------------------------------|-------------------------------------------------------------------|----------| | storeName | string | Name of the collection to modify. | Yes | | newSchema | SchemaDefinition<SchemaDefinitionType<U>> | New schema definition for the collection. | Yes | | changeValues | Record<string, any> | Update operations to apply to existing documents. | Yes |

Returns:

  • Promise<void>: Resolves when the schema is updated, or rejects with an error.

Example:

const newSchema = {
  name: { type: String, required: true },
  email: { type: String, required: true },
  age: { type: Number, default: 0 },
};

await db.alterStore('users', newSchema, { $set: { age: 18 } });
console.log('Users schema updated');

findAndPopulateById

Retrieves documents by ID and populates specified fields.

Signature:

async findAndPopulateById<T>(
  storeName: string,
  thingsToBePopulated: string | string[],
  query: Record<string, any>
): Promise<T[]>

Parameters:

| Parameter | Type | Description | Required | |-----------------------|-------------------------|----------------------------------------------------------|----------| | storeName | string | Name of the collection to query. | Yes | | thingsToBePopulated | string | string[] | Field(s) to populate (e.g., 'posts' or ['posts', 'comments']). | Yes | | query | Record<string, any> | Query to filter documents (e.g., { _id: '123' }). | Yes |

Returns:

  • Promise<T[]>: An array of documents with populated fields.

Example:

const user = await db.findAndPopulateById('users', 'posts', { _id: '123' });
console.log(user); // [{ name: 'John', posts: [{ title: 'Post 1', ... }, ...] }]

aggregate

Executes an aggregation pipeline on a collection.

Signature:

async aggregate<T>(
  storeName: string,
  pipeline: any
): Promise<any[]>

Parameters:

| Parameter | Type | Description | Required | |--------------|----------|----------------------------------------------------------|----------| | storeName | string | Name of the collection to aggregate. | Yes | | pipeline | any | Array of aggregation pipeline stages. | Yes |

Returns:

  • Promise<any[]>: An array of aggregation results.

Example:

const pipeline = [
  { $match: { name: 'John Doe' } },
  { $group: { _id: '$email', count: { $sum: 1 } } },
];

const results = await db.aggregate('users', pipeline);
console.log(results); // [{ _id: '[email protected]', count: 1 }, ...]

pipelineBuilder

Creates an instance of AggregationBuilder for constructing aggregation pipelines.

Signature:

pipelineBuilder(): AggregationBuilder

Returns:

  • AggregationBuilder: An instance of the aggregation builder.

Example:

const builder = db.pipelineBuilder();
const pipeline = builder
  .match('status', { eq: 'active' })
  .group('userId')
  .sum('amount', 'totalSpent')
  .build();

const results = await db.aggregate('orders', pipeline);
console.log(results);

createIndex

Creates an index on a specified column in a collection.

Signature:

async createIndex(
  storeName: string,
  column: string,
  order: string,
  options: any
): Promise<void>

Parameters:

| Parameter | Type | Description | Required | |-------------|----------|----------------------------------------------------------|----------| | storeName | string | Name of the collection to create the index on. | Yes | | column | string | Field to index (e.g., 'email'). | Yes | | order | string | Index order (e.g., '1' for ascending, '-1' for descending). | Yes | | options | any | Additional index options (e.g., { unique: true }). | Yes |

Returns:

  • Promise<void>: Resolves when the index is created, or rejects with an error.

Example:

await db.createIndex('users', 'email', '1', { unique: true });
console.log('Index created on email');

viewIndexes

Retrieves all indexes for a collection.

Signature:

async viewIndexes(storeName: string): Promise<IndexDefinition[]>

Parameters:

| Parameter | Type | Description | Required | |-------------|----------|----------------------------------------------------------|----------| | storeName | string | Name of the collection to view indexes for. | Yes |

Returns:

  • Promise<IndexDefinition[]>: An array of index definitions.

Example:

const indexes = await db.viewIndexes('users');
console.log(indexes); // [{ key: { email: 1 }, name: 'email_1', ... }, ...]

dropIndex

Drops a specified index from a collection.

Signature:

async dropIndex(storeName: string, indexName: string): Promise<void>

Parameters:

| Parameter | Type | Description | Required | |--------------|----------|----------------------------------------------------------|----------| | storeName | string | Name of the collection to drop the index from. | Yes | | indexName | string | Name of the index to drop (e.g., 'email_1'). | Yes |

Returns:

  • Promise<void>: Resolves when the index is dropped, or rejects with an error.

Example:

await db.dropIndex('users', 'email_1');
console.log('Index dropped');

findAndPopulateByKey

Retrieves documents from one collection and populates fields from another collection based on a key relationship.

Signature:

async findAndPopulateByKey(
  fromStoreName: string,
  query: Record<string, any>,
  fromKey: string,
  findInStoreName: string,
  inKey: string
): Promise<any[]>

Parameters:

| Parameter | Type | Description | Required | |-------------------|-------------------------|----------------------------------------------------------|----------| | fromStoreName | string | Name of the source collection. | Yes | | query | Record<string, any> | Query to filter source documents. | Yes | | fromKey | string | Field in the source collection to match. | Yes | | findInStoreName | string | Name of the collection to populate from. | Yes | | inKey | string | Field in the target collection to match against fromKey. | Yes |

Returns:

  • Promise<any[]>: An array of documents with populated fields.

Example:

const users = await db.findAndPopulateByKey(
  'users',
  { name: 'John Doe' },
  'userId',
  'posts',
  'authorId'
);
console.log(users); // [{ name: 'John Doe', posts: [{ title: 'Post 1', ... }, ...] }]

startTransaction

Starts a new transaction session.

Signature:

async startTransaction(): Promise<void>

Returns:

  • Promise<void>: Resolves when the transaction session is started, or rejects with an error.

Example:

await db.startTransaction();
console.log('Transaction started');

commitTransaction

Commits the current transaction.

Signature:

async commitTransaction(): Promise<void>

Returns:

  • Promise<void>: Resolves when the transaction is committed, or rejects with an error.

Example:

await db.commitTransaction();
console.log('Transaction committed');

abortTransaction

Aborts the current transaction.

Signature:

async abortTransaction(): Promise<void>

Returns:

  • Promise<void>: Resolves when the transaction is aborted, or rejects with an error.

Example:

await db.abortTransaction();
console.log('Transaction aborted');

getSession

Retrieves the current Mongoose session, if one exists.

Signature:

async getSession(): Promise<mongoose.ClientSession | null>

Returns:

  • Promise<mongoose.ClientSession | null>: The current session or null if no session exists.

Example:

const session = await db.getSession();
if (session) {
  console.log('Active session retrieved');
} else {
  console.log('No active session');
}

getMongoose

Retrieves the Mongoose instance used by the wrapper.

Signature:

async getMongoose(): Promise<typeof mongoose>

Returns:

  • Promise<typeof mongoose>: The Mongoose instance.

Example:

const mongoose = await db.getMongoose();
console.log('Mongoose instance retrieved:', mongoose.version);

disconnect

Closes the connection to the MongoDB database.

Signature:

async disconnect(): Promise<void>

Returns:

  • Promise<void>: Resolves when the connection is closed, or rejects with an error.

Example:

await db.disconnect();
console.log('Database disconnected');

AggregationBuilder Methods

The AggregationBuilder class simplifies MongoDB’s aggregation pipelines with a fluent, chainable API. It supports a comprehensive set of pipeline stages and operators, making complex data transformations accessible to beginners and powerful for advanced users. Below are the methods provided in the class, each with a description, parameters, and example.

match

Filters documents based on a field and condition, using a mapped operator (e.g., eq, gt) from operatorMap.

Signature:

match(field: string, condition: Record<string, any>): this

Parameters:

| Parameter | Type | Description | Required | |-------------|-------------------------|----------------------------------------------------------|----------| | field | string | Field to filter on. | Yes | | condition | Record<string, any> | Condition object with operators (e.g., { eq: 'active' }). | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .match('status', { eq: 'active' })
  .build();

group

Groups documents by a field or composite key, enabling accumulator operations.

Signature:

group(groupBy: string | Record<string, any>): this

Parameters:

| Parameter | Type | Description | Required | |------------|-------------------------|----------------------------------------------------------|----------| | groupBy | string | Record<string, any> | Field name or object for composite grouping key. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .group('userId')
  .build();

sum

Adds a $sum accumulator to the last group stage.

Signature:

sum(value: string, key: string): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | value | string | Field to sum. | Yes | | key | string | Output field name for the sum. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .group('userId')
  .sum('amount', 'totalSpent')
  .build();

avg

Adds an $avg accumulator to the last group stage.

Signature:

avg(value: string, key: string): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | value | string | Field to average. | Yes | | key | string | Output field name for the average. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .group('userId')
  .avg('score', 'averageScore')
  .build();

min

Adds a $min accumulator to the last group stage.

Signature:

min(value: string, key: string): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | value | string | Field to find the minimum of. | Yes | | key | string | Output field name for the minimum. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .group('userId')
  .min('price', 'minPrice')
  .build();

max

Adds a $max accumulator to the last group stage.

Signature:

max(value: string, key: string): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | value | string | Field to find the maximum of. | Yes | | key | string | Output field name for the maximum. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .group('userId')
  .max('price', 'maxPrice')
  .build();

first

Adds a $first accumulator to the last group stage.

Signature:

first(value: string, key: string): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | value | string | Field to select the first value of. | Yes | | key | string | Output field name for the first value. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .group('userId')
  .first('name', 'firstName')
  .build();

last

Adds a $last accumulator to the last group stage.

Signature:

last(value: string, key: string): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | value | string | Field to select the last value of. | Yes | | key | string | Output field name for the last value. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .group('userId')
  .last('name', 'lastName')
  .build();

push

Adds a $push accumulator to the last group stage, collecting values into an array.

Signature:

push(field: string, key: string = field): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | field | string | Field to collect (or 'ENTIRE' for the entire document). | Yes | | key | string | Output field name for the array (defaults to field). | No |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .group('userId')
  .push('orderId', 'orders')
  .build();

addToSet

Adds an $addToSet accumulator to the last group stage, collecting unique values into an array.

Signature:

addToSet(value: string, key: string): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | value | string | Field to collect unique values from. | Yes | | key | string | Output field name for the unique array. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .group('userId')
  .addToSet('category', 'categories')
  .build();

stdDevPop

Adds a $stdDevPop accumulator to the last group stage for population standard deviation.

Signature:

stdDevPop(value: string, key: string): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | value | string | Field to calculate population standard deviation. | Yes | | key | string | Output field name for the result. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .group('userId')
  .stdDevPop('score', 'scoreStdDevPop')
  .build();

stdDevSamp

Adds a $stdDevSamp accumulator to the last group stage for sample standard deviation.

Signature:

stdDevSamp(value: string, key: string): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | value | string | Field to calculate sample standard deviation. | Yes | | key | string | Output field name for the result. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .group('userId')
  .stdDevSamp('score', 'scoreStdDevSamp')
  .build();

mergeObjects

Adds a $mergeObjects accumulator to the last group stage to combine documents.

Signature:

mergeObjects(value: string, key: string): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | value | string | Field containing objects to merge. | Yes | | key | string | Output field name for the merged object. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .group('userId')
  .mergeObjects('details', 'mergedDetails')
  .build();

count

Adds a $sum: 1 accumulator to the last group stage to count documents.

Signature:

count(key: string = 'count'): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | key | string | Output field name for the count (defaults to 'count'). | No |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .group('userId')
  .count('userCount')
  .build();

project

Specifies fields to include or exclude in the output.

Signature:

project(projection: Record<string, any>): this

Parameters:

| Parameter | Type | Description | Required | |--------------|-------------------------|----------------------------------------------------------|----------| | projection | Record<string, any> | Object specifying fields to include (1) or exclude (0). | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .project({ name: 1, email: 1, _id: 0 })
  .build();

sort

Sorts documents by specified fields.

Signature:

sort(sortFields: Record<string, 'asc' | 'desc'>): this

Parameters:

| Parameter | Type | Description | Required | |---------------|-----------------------------------|----------------------------------------------------------|----------| | sortFields | Record<string, 'asc' | 'desc'> | Object mapping fields to sort direction (asc or desc). | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .sort({ totalSpent: 'desc' })
  .build();

limit

Limits the number of documents returned.

Signature:

limit(n: number): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | n | number | Maximum number of documents to return. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .limit(10)
  .build();

skip

Skips a specified number of documents.

Signature:

skip(n: number): this

Parameters:

| Parameter | Type | Description | Required | |-----------|----------|----------------------------------------------------------|----------| | n | number | Number of documents to skip. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .skip(5)
  .build();

lookup

Performs a left outer join with another collection.

Signature:

lookup(from: string, localField: string, foreignField: string, as: string): this

Parameters:

| Parameter | Type | Description | Required | |----------------|----------|----------------------------------------------------------|----------| | from | string | Name of the collection to join with. | Yes | | localField | string | Field from the input documents. | Yes | | foreignField | string | Field from the from collection. | Yes | | as | string | Name of the output array field. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .lookup('posts', 'userId', 'authorId', 'userPosts')
  .build();

unset

Removes specified fields from documents.

Signature:

unset(...fields: string[]): this

Parameters:

| Parameter | Type | Description | Required | |-----------|------------|----------------------------------------------------------|----------| | fields | string[] | Fields to remove from documents. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .unset('password', 'token')
  .build();

addFields

Adds new fields to documents.

Signature:

addFields(fields: Record<string, any>): this

Parameters:

| Parameter | Type | Description | Required | |-----------|-------------------------|----------------------------------------------------------|----------| | fields | Record<string, any> | Object specifying new fields and their values. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .addFields({ fullName: { $concat: ['$firstName', ' ', '$lastName'] } })
  .build();

replaceRoot

Replaces the document with a specified new root.

Signature:

replaceRoot(newRoot: any): this

Parameters:

| Parameter | Type | Description | Required | |------------|----------|----------------------------------------------------------|----------| | newRoot | any | Expression defining the new root document. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .replaceRoot('$details')
  .build();

replaceWith

Replaces the document with a specified value.

Signature:

replaceWith(replacement: any): this

Parameters:

| Parameter | Type | Description | Required | |---------------|----------|----------------------------------------------------------|----------| | replacement | any | Expression defining the replacement document. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .replaceWith('$details')
  .build();

graphLookup

Performs a recursive search on a collection.

Signature:

graphLookup(options: {
  from: string;
  startWith: any;
  connectFromField: string;
  connectToField: string;
  as: string;
  maxDepth?: number;
  depthField?: string;
  restrictSearchWithMatch?: Record<string, any>;
}): this

Parameters:

| Parameter | Type | Description | Required | |----------------------------|-------------------------|----------------------------------------------------------|----------| | options.from | string | Collection to perform the lookup on. | Yes | | options.startWith | any | Expression to start the graph lookup. | Yes | | options.connectFromField | string | Field to connect from. | Yes | | options.connectToField | string | Field to connect to. | Yes | | options.as | string | Output array field name. | Yes | | options.maxDepth | number | Maximum recursion depth (optional). | No | | options.depthField | string | Field to store depth (optional). | No | | options.restrictSearchWithMatch | Record<string, any> | Match conditions to restrict search (optional). | No |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .graphLookup({
    from: 'employees',
    startWith: '$managerId',
    connectFromField: 'managerId',
    connectToField: '_id',
    as: 'reportingHierarchy',
  })
  .build();

unwind

Deconstructs an array field into multiple documents.

Signature:

unwind(field: string | Record<string, any>): this

Parameters:

| Parameter | Type | Description | Required | |-----------|-------------------------|----------------------------------------------------------|----------| | field | string | Record<string, any> | Field to unwind or unwind options object. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .unwind('items')
  .build();

bucket

Groups documents into buckets based on a specified expression.

Signature:

bucket(options: {
  groupBy: any;
  boundaries: any[];
  default?: any;
  output: Record<string, any>;
}): this

Parameters:

| Parameter | Type | Description | Required | |---------------------|-------------------------|----------------------------------------------------------|----------| | options.groupBy | any | Expression to group by. | Yes | | options.boundaries| any[] | Array of bucket boundaries. | Yes | | options.default | any | Default bucket for non-matching documents (optional). | No | | options.output | Record<string, any> | Output specification for each bucket. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .bucket({
    groupBy: '$price',
    boundaries: [0, 100, 200, 300],
    default: 'other',
    output: { count: { $sum: 1 } },
  })
  .build();

bucketAuto

Automatically groups documents into a specified number of buckets.

Signature:

bucketAuto(options: {
  groupBy: any;
  buckets: number;
  output?: Record<string, any>;
  granularity?: string;
}): this

Parameters:

| Parameter | Type | Description | Required | |----------------------|-------------------------|----------------------------------------------------------|----------| | options.groupBy | any | Expression to group by. | Yes | | options.buckets | number | Number of buckets. | Yes | | options.output | Record<string, any> | Output specification for each bucket (optional). | No | | options.granularity| string | Granularity for numeric bucketing (optional). | No |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .bucketAuto({
    groupBy: '$price',
    buckets: 5,
    output: { count: { $sum: 1 } },
  })
  .build();

facet

Processes multiple aggregation pipelines within a single stage.

Signature:

facet(facets: Record<string, any[]>): this

Parameters:

| Parameter | Type | Description | Required | |-----------|-------------------------|----------------------------------------------------------|----------| | facets | Record<string, any[]> | Object mapping facet names to pipeline arrays. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .facet({
    byCategory: [{ $group: { _id: '$category', count: { $sum: 1 } } }],
    byPrice: [{ $bucket: { groupBy: '$price', boundaries: [0, 100, 200] } }],
  })
  .build();

merge

Writes the results of the pipeline to a collection.

Signature:

merge(options: string | Record<string, any>): this

Parameters:

| Parameter | Type | Description | Required | |-----------|-------------------------|----------------------------------------------------------|----------| | options | string | Record<string, any> | Collection name or merge options object. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .merge('outputCollection')
  .build();

out

Writes the pipeline results to a collection, replacing its contents.

Signature:

out(collectionName: string): this

Parameters:

| Parameter | Type | Description | Required | |------------------|----------|----------------------------------------------------------|----------| | collectionName | string | Name of the collection to write to. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .out('results')
  .build();

search

Adds a $search stage for Atlas Search.

Signature:

search(searchStage: Record<string, any>): this

Parameters:

| Parameter | Type | Description | Required | |---------------|-------------------------|----------------------------------------------------------|----------| | searchStage | Record<string, any> | Search stage configuration. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .search({ text: { query: 'example', path: 'description' } })
  .build();

searchMeta

Adds a $searchMeta stage for Atlas Search metadata.

Signature:

searchMeta(searchStage: Record<string, any>): this

Parameters:

| Parameter | Type | Description | Required | |---------------|-------------------------|----------------------------------------------------------|----------| | searchStage | Record<string, any> | Search metadata stage configuration. | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .searchMeta({ count: { type: 'total' } })
  .build();

redact

Restricts document content based on an expression.

Signature:

redact(expression: any): this

Parameters:

| Parameter | Type | Description | Required | |--------------|----------|----------------------------------------------------------|----------| | expression | any | Redaction expression (e.g., $cond). | Yes |

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .redact({
    $cond: { if: { $eq: ['$level', 'public'] }, then: '$$KEEP', else: '$$PRUNE' },
  })
  .build();

indexStats

Adds an $indexStats stage to retrieve index statistics.

Signature:

indexStats(): this

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .indexStats()
  .build();

currentOp

Adds a $currentOp stage to retrieve current operations.

Signature:

currentOp(): this

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .currentOp()
  .build();

collStats

Adds a $collStats stage to retrieve collection statistics.

Signature:

collStats(): this

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .collStats()
  .build();

planCacheStats

Adds a $planCacheStats stage to retrieve query plan cache statistics.

Signature:

planCacheStats(): this

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .planCacheStats()
  .build();

listSessions

Adds a $listSessions stage to retrieve active sessions.

Signature:

listSessions(): this

Returns:

  • this: The AggregationBuilder instance for chaining.

Example:

const pipeline = db.pipelineBuilder()
  .listSessions()
  .build();

build

Returns the constructed aggregation pipeline.

Signature:

build(): any[]

Returns:

  • any[]: The array of pipeline stages.

Example:

const pipeline = db.pipelineBuilder()
  .match('status', { eq: 'active' })
  .group('userId')
  .sum('amount', 'totalSpent')
  .build();
console.log(pipeline); // [{ $match: ... }, { $group: ... }]

Advanced Usage

Mongo-Bolt supports advanced MongoDB features, making it suitable for complex applications. The following sections, inspired by Hashnode Docs’ focus on interactivity, provide guidance on leveraging these capabilities.

Transaction Management

Mongo-Bolt supports MongoDB transactions for atomic operations across multiple collections. Use startTransaction, commitTransaction, abortTransaction, and getSession to manage transactions.

Example:

const db = new MongoDB(config);
await db.connect();

try {
  await db.startTransaction();

  const session = await db.getSession();
  const user = { name: 'Alice', email: '[email protected]' };
  await db.insertItem('users', user, { session });

  const post = { title: 'First Post', author: 'Alice' };
  await db.insertItem('posts', post, { session });

  await db.commitTransaction();
  console.log('Transaction committed');
} catch (error) {
  await db.abortTransaction();
  console.error('Transaction aborted:', error.message);
} finally {
  await db.disconnect();
}

Aggregation Pipelines

The aggregate method and AggregationBuilder enable powerful data aggregation. The AggregationBuilder provides a fluent interface, simplifying complex pipelines.

Example:

const builder = db.pipelineBuilder();
const pipeline = builder
  .match('status', { eq: 'active' })
  .group('userId')
  .sum('amount', 'totalSpent')
  .sort({ totalSpent: 'desc' })
  .limit(10)
  .build();

const topSpenders = await db.aggregate('orders', pipeline);
console.log(topSpenders);

Index Management

Indexes optimize query performance. Use createIndex, viewIndexes, and dropIndex to manage indexes.

Example:

// Create a unique index
await db.createIndex('users', 'email', '1', { unique: true });

// View all indexes
const indexes = await db.viewIndexes('users');
console.log(indexes);

// Drop an index
await db.dropIndex('users', 'email_1');
console.log('Index dropped');

Examples

The following examples demonstrate Mongo-Bolt’s capabilities in real-world scenarios, designed to be interactive and clear, as inspired by Hashnode Docs.

Complete CRUD Workflow

This example shows a full CRUD workflow, from creating a collection to deleting a document.

import MongoDB from 'mongo-bolt';
import { Schema } from 'mongoose';

const config = {
  uri: 'mongodb://localhost:27017/mydb',
  options: { useNewUrlParser: true, useUnifiedTopology: true },
};

const db = new MongoDB(config);

async function run() {
  try {
    // Connect to database
    await db.connect();

    // Create a collection
    const userSchema = {
      name: { type: String, required: true },
      email: { type: String, required: true },
    };
    await db.createStore('users', userSchema);

    // Insert a document
    await db.insertItem('users', { name: 'Alice', email: '[email protected]' });

    // Find documents
    const users = await db.findItem('users', { name: 'Alice' });
    console.log(users);

    // Update documents
    await db.updateItems('users', { name: 'Alice' }, { $set: { email: '[email protected]' } });

    // Delete a document
    await db.dropItem('users', { email: '[email protected]' });

    // Disconnect
    await db.disconnect();
  } catch (error) {
    console.error('Error:', error.message);
  }
}

run();

Populating Related Data

This example demonstrates how to populate related data across collections.

import MongoDB from 'mongo-bolt';
import { Schema } from 'mongoose';

const userSchema = {
  name: { type: String, required: true },
  postIds: [{ type: Schema.Types.ObjectId, ref: 'posts' }],
};

const postSchema = {
  title: { type: String, required: true },
  authorId: { type: Schema.Types.ObjectId, ref: 'users' },
};

const db = new MongoDB(config);
await db.connect();
await db.createStore('users', userSchema);
await db.createStore('posts', postSchema);

const users = await db.findAndPopulateById('users', 'postIds', { name: 'John' });
console.log(users); // [{ name: 'John', postIds: [{ title: 'Post 1', ... }, ...] }]
await db.disconnect();

Building an Aggregation Pipeline

This example shows how to use AggregationBuilder for advanced data analysis.

const builder = db.pipelineBuilder();
const pipeline = builder
  .match('status', { eq: 'active' })
  .group('category')
  .sum('price', 'total')
  .sort({ total: 'desc' })
  .limit(5)
  .build();

const results = await db.aggregate('products', pipeline);
console.log(results); // [{ _id: 'electronics', total: 5000 }, ...]

Error Handling

Mongo-Bolt methods throw errors for invalid states (e.g., uninitialized connector) or database issues. Use try-catch blocks to handle errors, as recommended in robust documentation like Hashnode Docs.

Example:

try {
  await db.insertItem('users', { name: 'Invalid User' });
} catch (error) {
  console.error('Failed to insert user:', error.message);
}

Contributing

Contributions to Mongo-Bolt are welcome! To contribute:

  1. Fork the repository on GitHub.
  2. Create a feature branch (git checkout -b feature/your-feature).
  3. Commit your changes (git commit -m 'Add your feature').
  4. Push to the branch (git push origin feature/your-feature).
  5. Open a pull request.

Please include tests and update documentation for new features, aligning with the collaborative workflows emphasized by Hashnode Docs.

License

MIT License. See LICENSE for details.