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 🙏

© 2026 – Pkg Stats / Ryan Hefner

pnk-node-mongo

v1.2.2

Published

A lightweight Node.js MongoDB utility library providing CRUD operations, pagination, filtering, sorting, and aggregation with Mongoose support.

Readme

pnk-node-mongo

A modern MongoDB helper library built on top of Mongoose with optional Pinaka Response support and 100% backward compatibility.

npm version npm downloads License Node.js Mongoose

A lightweight wrapper around Mongoose that reduces boilerplate code while keeping the flexibility of native Mongoose.

Designed for both new projects and legacy Pinaka Framework applications, pnk-node-mongo provides a clean, modern API while maintaining full backward compatibility.


Features

  • Modern Promise-based API
  • Built on top of Mongoose
  • Zero configuration
  • Supports MongoDB 6+
  • Supports Mongoose 6 / 7 / 8
  • Supports Node.js 18+
  • CRUD helper methods
  • Aggregation helpers
  • Populate support
  • Pagination support
  • Distinct support
  • Optional Pinaka Response format
  • Legacy API compatibility
  • TypeScript definitions included
  • No performance overhead
  • Easy migration from older projects

Why pnk-node-mongo?

Most MongoDB helper libraries are either:

  • Too simple and require writing repetitive Mongoose code.
  • Too complex and introduce unnecessary abstractions.
  • Not backward compatible with existing codebases.

pnk-node-mongo is designed to provide the best balance between simplicity, flexibility, and productivity.

Working with Mongoose often involves writing repetitive code for:

  • Pagination
  • Filtering
  • Sorting
  • Field selection
  • Population
  • Aggregation
  • Response formatting

This library removes that boilerplate while keeping the power of Mongoose.

Instead of writing:

const users = await User.find({
    status: true
})
.sort({ created_on: -1 })
.skip(20)
.limit(10)
.select("name email");

You can simply write:

const users = await db.find(User, {
    filter: {
        status: true
    },
    sort: {
        created_on: -1
    },
    page: 3,
    limit: 10,
    select: [
        "name",
        "email"
    ]
});

Less code.

More readable.

Easier to maintain.


Table of Contents

  • Installation
  • Quick Start
  • CRUD Operations
    • find()
    • findOne()
    • create()
    • createMany()
    • updateOne()
    • updateMany()
    • deleteOne()
    • deleteMany()
    • distinct()
    • findOneAndUpdate()
  • Populate
  • Aggregation
  • Response Mode
  • Legacy Compatibility
  • Migration Guide
  • TypeScript
  • API Reference
  • Examples
  • FAQ
  • Roadmap
  • Contributing
  • License
  • Changelog

Requirements

| Package | Version | |---------|----------| | Node.js | 18+ | | MongoDB | 6+ | | Mongoose | 6.x / 7.x / 8.x |


Installation

npm install pnk-node-mongo

or

yarn add pnk-node-mongo

Quick Start

Import

const db = require("pnk-node-mongo");

Basic Example

const users = await db.find(User, {
    filter: {
        status: true
    }
});

console.log(users);

Response Mode Example

const result = await db.find(User, {
    response: "users",
    filter: {
        status: true
    }
});

Output

{
    users: {
        metarow: {
            totalRecordsInCurrentSet: 5,
            totalRecordsInDb: 25,
            totalRecordsInSet: 10,
            setNo: 1
        },
        rows: [
            ...
        ]
    },
    PinakaResponse: {
        ServerStatus: {
            value: "SUCCESS"
        }
    }
}

Project Philosophy

The goal of pnk-node-mongo is simple:

  • Keep the simplicity of Mongoose
  • Reduce repetitive code
  • Provide consistent APIs
  • Preserve backward compatibility
  • Make migration effortless
  • Improve developer productivity

The library is intentionally lightweight and acts as a thin wrapper over Mongoose without introducing unnecessary abstractions or performance overhead.



CRUD Operations

All CRUD methods are Promise-based and internally use Mongoose.

Import the library:

const db = require("pnk-node-mongo");

find()

Fetch multiple documents.

Syntax

db.find(Model, options)

Parameters

| Option | Type | Description | |---------|------|-------------| | filter | Object | Query filter | | sort | Object | Sorting | | page | Number | Page number (starts from 1) | | limit | Number | Records per page | | select | Array | Fields to include | | exclude | Array | Fields to exclude | | response | String | Optional Pinaka Response key |


Example 1

const users = await db.find(User,{
    filter:{
        status:true
    }
});

Example 2 - Pagination

const users = await db.find(User,{
    page:2,
    limit:20
});

Example 3 - Sorting

const users = await db.find(User,{
    sort:{
        created_on:-1
    }
});

Example 4 - Filter + Pagination

const users = await db.find(User,{
    filter:{
        city:"Pune",
        status:true
    },
    page:1,
    limit:10
});

Example 5 - Select Fields

const users = await db.find(User,{
    select:[
        "name",
        "email",
        "mobile"
    ]
});

Example 6 - Exclude Fields

const users = await db.find(User,{
    exclude:[
        "__v",
        "password"
    ]
});

Example 7 - Response Mode

const result = await db.find(User,{
    response:"users",
    filter:{
        status:true
    }
});

Legacy Equivalent

PnkFetchAll(...)

findOne()

Fetch a single document.

Syntax

db.findOne(Model, options)

Example 1

const user = await db.findOne(User,{
    filter:{
        _id:userId
    }
});

Example 2

const user = await db.findOne(User,{
    filter:{
        email:"[email protected]"
    }
});

Example 3

const user = await db.findOne(User,{
    filter:{
        mobile:"9876543210"
    },
    select:[
        "name",
        "email"
    ]
});

Example 4

const result = await db.findOne(User,{
    response:"user",
    filter:{
        email:"[email protected]"
    }
});

Legacy Equivalent

PnkFetchOne(...)

create()

Insert one document.

Syntax

db.create(Model,data,options)

Example

await db.create(User,{
    name:"John",
    email:"[email protected]",
    mobile:"9999999999"
});

Response Mode

await db.create(
    User,
    {
        name:"John"
    },
    {
        response:"user"
    }
);

Legacy Equivalent

PnkAddNew(...)

createMany()

Insert multiple documents.

Example

await db.createMany(User,[
    {
        name:"John"
    },
    {
        name:"David"
    },
    {
        name:"Robert"
    }
]);

updateOne()

Update a single document.

New Style

await db.updateOne(User,{
    filter:{
        _id:id
    },
    update:{
        name:"Peter"
    }
});

Old Style

await db.updateOne(
    User,
    {
        _id:id
    },
    {
        $set:{
            name:"Peter"
        }
    }
);

Response Mode

await db.updateOne(
    User,
    {
        filter:{
            _id:id
        },
        update:{
            status:true
        },
        response:"user"
    }
);

Legacy Equivalent

PnkUpdate(...)

updateMany()

Update multiple documents.

await db.updateMany(User,{
    filter:{
        city:"Pune"
    },
    update:{
        verified:true
    }
});

Old Style

await db.updateMany(
    User,
    {
        city:"Pune"
    },
    {
        $set:{
            verified:true
        }
    }
);

deleteOne()

Delete a single document.

await db.deleteOne(User,{
    _id:id
});

Response Mode

await db.deleteOne(
    User,
    {
        _id:id
    },
    {
        response:"user"
    }
);

Legacy Equivalent

PnkDelete(...)

deleteMany()

Delete multiple documents.

await db.deleteMany(User,{
    status:false
});

distinct()

Fetch unique values.

Example

const cities = await db.distinct(User,{
    distinct_key:"city"
});

With Filter

const cities = await db.distinct(User,{
    distinct_key:"city",
    filter:{
        status:true
    }
});

Legacy Equivalent

PnkFetchDistinct(...)

findOneAndUpdate()

Update and return updated document.

Example

const user = await db.findOneAndUpdate(User,{
    filter:{
        _id:id
    },
    update:{
        status:true
    }
});

Return Selected Fields

const user = await db.findOneAndUpdate(User,{
    filter:{
        _id:id
    },
    update:{
        status:true
    },
    onlyFields:"name,email,status"
});

Exclude Fields

const user = await db.findOneAndUpdate(User,{
    filter:{
        _id:id
    },
    update:{
        status:true
    },
    exceptFields:"password,__v"
});

Legacy Equivalent

PnkFindAndModify(...)

Notes

  • All methods return Promises.
  • All methods support async/await.
  • Pagination starts from page 1.
  • response is optional.
  • Without response, methods return native Mongoose results.
  • With response, methods return Pinaka Response format.
  • All methods work with existing Mongoose models.

Migration Guide

Backward Compatibility

pnk-node-mongo v1.2.x is 100% backward compatible.

You can upgrade without changing any existing code.

All legacy methods continue to work exactly as before.

const db = require("pnk-node-mongo");

const result = await db.PnkFetchAll(
    "users",
    UserModel,
    {
        page: 1,
        per_set: 10,
        search_data: {
            status: true
        },
        sorting: {
            name: 1
        }
    }
);

New Recommended API

The same query can now be written in a much cleaner way.

const db = require("pnk-node-mongo");

const result = await db.find(UserModel, {
    response: "users",
    page: 1,
    limit: 10,
    filter: {
        status: true
    },
    sort: {
        name: 1
    }
});

Find One

Legacy

await db.PnkFetchOne(
    "user",
    UserModel,
    {
        search_data: {
            _id: userId
        }
    }
);

New

await db.findOne(UserModel, {
    response: "user",
    filter: {
        _id: userId
    }
});

Create Document

Legacy

await db.PnkAddNew({
    respKey: "user",
    model: UserModel,
    data: req.body
});

New

await db.create(
    UserModel,
    req.body,
    {
        response: "user"
    }
);

Create Multiple Documents

Legacy

await db.PnkAddNew({
    respKey: "users",
    model: UserModel,
    data: usersArray,
    multi: true
});

New

await db.createMany(
    UserModel,
    usersArray,
    {
        response: "users"
    }
);

Update One

Legacy

await db.PnkUpdate({
    respKey: "user",
    model: UserModel,
    filter: {
        _id: userId
    },
    updateData: {
        $set: {
            status: true
        }
    }
});

New

await db.updateOne(UserModel, {
    response: "user",
    filter: {
        _id: userId
    },
    update: {
        $set: {
            status: true
        }
    }
});

Update Many

Legacy

await db.PnkUpdate({
    respKey: "users",
    model: UserModel,
    filter: {
        status: false
    },
    updateData: {
        $set: {
            status: true
        }
    },
    multi: true
});

New

await db.updateMany(UserModel, {
    response: "users",
    filter: {
        status: false
    },
    update: {
        $set: {
            status: true
        }
    }
});

Delete One

Legacy

await db.PnkDelete({
    respKey: "user",
    model: UserModel,
    filter: {
        _id: userId
    }
});

New

await db.deleteOne(UserModel, {
    _id: userId
});

Delete Many

Legacy

await db.PnkDelete({
    respKey: "users",
    model: UserModel,
    filter: {
        status: false
    },
    multi: true
});

New

await db.deleteMany(UserModel, {
    status: false
});

Populate

Legacy

await db.PnkFetchWithPopulate(
    "users",
    UserModel,
    {
        search_data: {
            status: true
        },
        populate: "role"
    }
);

New

await db.findPopulate(UserModel, {
    response: "users",
    filter: {
        status: true
    },
    populate: "role"
});

Distinct

Legacy

await db.PnkFetchDistinct(
    "cities",
    UserModel,
    {
        distinct_key: "city"
    }
);

New

await db.distinct(UserModel, {
    response: "cities",
    distinct_key: "city"
});

Aggregate

Legacy

await db.PnkAggregate(
    "report",
    UserModel,
    options
);

New

await db.aggregate(
    UserModel,
    options
);

Find One And Update

Legacy

await db.PnkFindAndModify({
    respKey: "user",
    model: UserModel,
    filter: {
        _id: userId
    },
    update: {
        $set: {
            status: true
        }
    }
});

New

await db.findOneAndUpdate(UserModel, {
    response: "user",
    filter: {
        _id: userId
    },
    update: {
        $set: {
            status: true
        }
    }
});

Upgrade Without Fear

✅ No breaking changes

✅ Existing code keeps working

✅ Gradually migrate to the cleaner API whenever you want

✅ Both APIs can be used together in the same project


API Reference

find()

Fetch multiple documents.

Syntax

db.find(model, options)

Parameters

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | model | Mongoose Model | ✅ | Mongoose model | | options | Object | ❌ | Query options |

Available Options

| Option | Type | Description | |---------|------|-------------| | response | String | Response key for legacy response format | | filter | Object | MongoDB filter | | page | Number | Page number | | limit | Number | Records per page | | sort | Object | Sorting | | select | Array | Fields to return | | exclude | Array | Fields to exclude |

Example

const users = await db.find(UserModel, {
    response: "users",
    page: 1,
    limit: 20,
    filter: {
        status: true
    },
    sort: {
        name: 1
    }
});

findOne()

Fetch a single document.

Syntax

db.findOne(model, options)

Example

const user = await db.findOne(UserModel, {
    response: "user",
    filter: {
        _id: userId
    }
});

findPopulate()

Fetch documents with populated references.

Syntax

db.findPopulate(model, options)

Example

const users = await db.findPopulate(UserModel, {
    response: "users",
    filter: {
        status: true
    },
    populate: [
        {
            path: "company_id",
            select: "company_name"
        },
        {
            path: "builder_id",
            select: "builder_name"
        }
    ]
});

distinct()

Returns distinct values of a field.

Syntax

db.distinct(model, options)

Example

const cities = await db.distinct(UserModel, {
    response: "cities",
    distinct_key: "city"
});

create()

Insert a single document.

Syntax

db.create(model, data, options)

Example

await db.create(
    UserModel,
    {
        name: "John",
        city: "Mumbai"
    },
    {
        response: "user"
    }
);

createMany()

Insert multiple documents.

Syntax

db.createMany(model, data, options)

Example

await db.createMany(
    UserModel,
    [
        {
            name: "John"
        },
        {
            name: "David"
        }
    ],
    {
        response: "users"
    }
);

updateOne()

Update one document.

Syntax

db.updateOne(model, options)

Example

await db.updateOne(UserModel, {
    response: "user",
    filter: {
        _id: userId
    },
    update: {
        $set: {
            city: "Pune"
        }
    }
});

updateMany()

Update multiple documents.

Syntax

db.updateMany(model, options)

Example

await db.updateMany(UserModel, {
    response: "users",
    filter: {
        active: false
    },
    update: {
        $set: {
            active: true
        }
    }
});

deleteOne()

Delete one document.

Syntax

db.deleteOne(model, filter)

Example

await db.deleteOne(UserModel, {
    _id: userId
});

deleteMany()

Delete multiple documents.

Syntax

db.deleteMany(model, filter)

Example

await db.deleteMany(UserModel, {
    status: false
});

aggregate()

Execute aggregation pipeline.

Syntax

db.aggregate(model, options)

Example

const report = await db.aggregate(UserModel, {
    search_content: {
        status: true
    },
    group_content: {
        _id: "$city",
        total: {
            $sum: 1
        }
    }
});

aggregateFetch()

Execute aggregation with pagination.

Syntax

db.aggregateFetch(model, options)

Example

const report = await db.aggregateFetch(UserModel, {
    match: {
        status: true
    },
    page: 1,
    per_set: 20
});

findOneAndUpdate()

Update and return the updated document.

Syntax

db.findOneAndUpdate(model, options)

Example

const user = await db.findOneAndUpdate(UserModel, {
    response: "user",
    filter: {
        _id: userId
    },
    update: {
        $set: {
            city: "Pune"
        }
    }
});

Legacy APIs

The following APIs remain available for backward compatibility.

db.PnkFetchAll()
db.PnkFetchOne()
db.PnkFetchDistinct()
db.PnkFetchWithPopulate()
db.PnkUpdate()
db.PnkAddNew()
db.PnkDelete()
db.PnkAggregate()
db.PnkAggregateFetch()
db.PnkFindAndModify()

These methods behave exactly as they did in previous versions.


Real World Examples

Basic Find

const users = await db.find(UserModel, {
    filter: {
        status: true
    }
});

Pagination

const users = await db.find(UserModel, {
    page: 2,
    limit: 20
});

Search with Multiple Filters

const users = await db.find(UserModel, {
    filter: {
        status: true,
        city: "Pune",
        role: "Admin"
    }
});

Sorting

const users = await db.find(UserModel, {
    sort: {
        createdAt: -1
    }
});

Ascending

sort: {
    name: 1
}

Descending

sort: {
    name: -1
}

Select Specific Fields

const users = await db.find(UserModel, {
    select: [
        "name",
        "email",
        "mobile"
    ]
});

Exclude Fields

const users = await db.find(UserModel, {
    exclude: [
        "__v",
        "password"
    ]
});

Find by ObjectId

const user = await db.findOne(UserModel, {
    filter: {
        _id: "687b4caa02d66fd733df8244"
    }
});

String ObjectIds are automatically converted into MongoDB ObjectIds.


Insert One Document

await db.create(
    UserModel,
    {
        name: "John",
        email: "[email protected]",
        city: "Pune"
    }
);

Insert Multiple Documents

await db.createMany(
    UserModel,
    [
        {
            name: "John"
        },
        {
            name: "David"
        },
        {
            name: "Alex"
        }
    ]
);

Update One

await db.updateOne(UserModel, {
    filter: {
        _id: userId
    },
    update: {
        $set: {
            city: "Mumbai"
        }
    }
});

Update Many

await db.updateMany(UserModel, {
    filter: {
        city: "Pune"
    },
    update: {
        $set: {
            active: true
        }
    }
});

Delete One

await db.deleteOne(UserModel, {
    _id: userId
});

Delete Many

await db.deleteMany(UserModel, {
    status: false
});

Populate Single Reference

const users = await db.findPopulate(UserModel, {
    populate: "company_id"
});

Populate Multiple References

const users = await db.findPopulate(UserModel, {
    populate: [
        {
            path: "company_id",
            select: "company_name"
        },
        {
            path: "builder_id",
            select: "builder_name"
        }
    ]
});

Distinct Values

const cities = await db.distinct(UserModel, {
    distinct_key: "city"
});

Find One and Update

const user = await db.findOneAndUpdate(UserModel, {
    filter: {
        _id: userId
    },
    update: {
        $set: {
            status: true
        }
    }
});

Aggregate Example

const report = await db.aggregate(UserModel, {
    search_content: {
        status: true
    },
    group_content: {
        _id: "$city",
        totalUsers: {
            $sum: 1
        }
    }
});

Aggregate with Pagination

const report = await db.aggregateFetch(UserModel, {
    match: {
        status: true
    },
    page: 1,
    per_set: 25
});

Legacy Response Format

const users = await db.find(UserModel, {
    response: "users",
    filter: {
        status: true
    }
});

Returns

{
    users: {
        metarow: {
            totalRecordsInCurrentSet: 10,
            totalRecordsInDb: 120,
            totalRecordsInSet: 10,
            setNo: 1
        },
        rows: [...]
    },
    PinakaResponse: {
        ServerStatus: {
            value: "SUCCESS"
        }
    }
}

Modern Response

If response is omitted, the library returns plain Mongoose data.

const users = await db.find(UserModel, {
    filter: {
        status: true
    }
});

Returns

[
    {
        _id: "...",
        name: "John"
    },
    {
        _id: "...",
        name: "David"
    }
]

Async / Await Example

async function getUsers() {

    try {

        const users = await db.find(UserModel, {
            filter: {
                status: true
            }
        });

        console.log(users);

    } catch (err) {

        console.error(err);

    }

}

Express.js Example

exports.GetUsers = async (req, res) => {

    try {

        const users = await db.find(UserModel, {
            filter: {
                status: true
            },
            sort: {
                createdAt: -1
            }
        });

        res.json(users);

    } catch (err) {

        res.status(500).json({
            error: err.message
        });

    }

};

Advanced Examples

Search + Pagination + Sorting

const users = await db.find(UserModel, {
    response: "users",
    page: 1,
    limit: 20,
    filter: {
        status: true,
        city: "Pune"
    },
    sort: {
        createdAt: -1
    }
});

Search with Multiple Conditions

const users = await db.find(UserModel, {
    filter: {
        status: true,
        company_id: companyId,
        builder_id: builderId,
        role: "Sales"
    }
});

Find Using MongoDB Operators

const users = await db.find(UserModel, {
    filter: {
        age: {
            $gte: 18
        },
        salary: {
            $lt: 50000
        }
    }
});

Using Regular Expressions

const users = await db.find(UserModel, {
    filter: {
        name: {
            $regex: "ram",
            $options: "i"
        }
    }
});

Using $in

const users = await db.find(UserModel, {
    filter: {
        city: {
            $in: [
                "Pune",
                "Mumbai",
                "Delhi"
            ]
        }
    }
});

Using $or

const users = await db.find(UserModel, {
    filter: {
        $or: [
            {
                city: "Pune"
            },
            {
                city: "Mumbai"
            }
        ]
    }
});

Nested Object Search

const users = await db.find(UserModel, {
    filter: {
        "address.city": "Pune"
    }
});

Find Active Users

const users = await db.find(UserModel, {
    filter: {
        status: true,
        deleted: false
    }
});

Populate with Selected Fields

const users = await db.findPopulate(UserModel, {
    populate: {
        path: "company_id",
        select: "company_name company_email"
    }
});

Populate Multiple Models

const bookings = await db.findPopulate(BookingModel, {
    populate: [
        {
            path: "builder_id",
            select: "builder_name"
        },
        {
            path: "company_id",
            select: "company_name"
        },
        {
            path: "customer_id",
            select: "customer_name mobile"
        }
    ]
});

Aggregate Total Users

const report = await db.aggregate(UserModel, {
    group_content: {
        _id: "$city",
        totalUsers: {
            $sum: 1
        }
    }
});

Aggregate with Match

const report = await db.aggregate(UserModel, {
    search_content: {
        status: true
    },
    group_content: {
        _id: "$city",
        totalUsers: {
            $sum: 1
        }
    }
});

Aggregate with Lookup

const report = await db.aggregateFetch(BookingModel, {

    match: {
        status: true
    },

    lookups: [
        {
            from: "crm_companies",
            localField: "company_id",
            foreignField: "_id",
            as: "company"
        }
    ],

    unwind: [
        "$company"
    ],

    page: 1,
    per_set: 20

});

Update if Record Exists

await db.updateOne(UserModel, {

    filter: {
        email: "[email protected]"
    },

    update: {
        $set: {
            city: "Pune"
        }
    }

});

Upsert Example

await db.findOneAndUpdate(UserModel, {

    filter: {
        email: "[email protected]"
    },

    update: {
        $set: {
            city: "Pune"
        }
    },

    options: {
        upsert: true
    }

});

Bulk Insert

const users = [];

for (let i = 1; i <= 1000; i++) {

    users.push({

        name: `User ${i}`,

        status: true

    });

}

await db.createMany(UserModel, users);

Soft Delete

await db.updateOne(UserModel, {

    filter: {
        _id: userId
    },

    update: {

        $set: {

            deleted: true

        }

    }

});

Hard Delete

await db.deleteOne(UserModel, {

    _id: userId

});

Using Legacy Response Format

const result = await db.find(UserModel, {

    response: "users",

    filter: {

        status: true

    }

});

Using Modern Response

const result = await db.find(UserModel, {

    filter: {

        status: true

    }

});

Error Handling

try {

    const users = await db.find(UserModel);

    console.log(users);

}
catch (err) {

    console.error(err);

}

Express Route Example

exports.GetCompanyList = async (req, res) => {

    try {

        const result = await db.find(CompanyModel, {

            response: "companylist",

            page: 1,

            limit: 20,

            sort: {

                company_name: 1

            }

        });

        res.send(result);

    }
    catch (err) {

        res.status(500).send(err);

    }

};

Backward Compatible

Already using previous versions?

No problem.

db.PnkFetchAll(...)
db.PnkFetchOne(...)
db.PnkUpdate(...)
db.PnkDelete(...)

continue to work exactly as before.


Modern API

The library now supports clean method names.

find()

findOne()

create()

createMany()

updateOne()

updateMany()

deleteOne()

deleteMany()

aggregate()

aggregateFetch()

findPopulate()

findOneAndUpdate()

Automatic ObjectId Conversion

No need to manually convert string IDs.

Instead of

{
    _id: new mongoose.Types.ObjectId(id)
}

just write

{
    _id: id
}

The library automatically converts valid ObjectId strings.


Legacy Response Support

If your application depends on the original Pinaka response format, simply provide the response key.

const result = await db.find(UserModel, {

    response: "users"

});

Response

{

    users: {

        rows: [ ],

        metarow: { }

    },

    PinakaResponse: { }

}

Plain Mongoose Response

Prefer plain arrays?

Simply omit the response property.

const users = await db.find(UserModel);

Returns

[
    {
        _id: "...",
        name: "John"
    }
]

Minimal Learning Curve

If you already know Mongoose, you already know pnk-node-mongo.

There are no custom query languages or complex configuration files.


Production Ready

Designed for real-world applications including:

  • CRM Systems
  • ERP Applications
  • HRMS
  • Hospital Management
  • School Management
  • Inventory Systems
  • Billing Software
  • Real Estate CRM
  • Multi-Tenant SaaS Applications

Built on Mongoose

No wrappers around MongoDB drivers.

No custom database engine.

No vendor lock-in.

Just clean APIs built on top of Mongoose.


Easy Migration

You can migrate gradually.

Old and new APIs can be used together in the same project.

No breaking changes.

No code rewrite required.


Best Practices

Following these recommendations will help you build cleaner, faster, and more maintainable applications with pnk-node-mongo.


1. Prefer the New API

✅ Recommended

const users = await db.find(UserModel, {
    filter: {
        status: true
    }
});

❌ Legacy (still supported)

const users = await db.PnkFetchAll(
    "users",
    UserModel,
    options
);

2. Always Use Pagination

Avoid loading an entire collection.

✅ Good

const users = await db.find(UserModel, {
    page: 1,
    limit: 20
});

❌ Bad

const users = await db.find(UserModel);

on collections containing millions of records.


3. Fetch Only Required Fields

Instead of loading every field,

const users = await db.find(UserModel, {
    select: [
        "name",
        "email",
        "mobile"
    ]
});

or exclude unwanted fields

const users = await db.find(UserModel, {
    exclude: [
        "__v",
        "password"
    ]
});

4. Use MongoDB Indexes

Large collections should always have indexes on frequently searched fields.

Example

UserSchema.index({
    email: 1
});

UserSchema.index({
    company_id: 1,
    status: 1
});

5. Use createMany() for Bulk Inserts

Instead of

for(const user of users){

    await db.create(UserModel,user);

}

Use

await db.createMany(UserModel, users);

This is significantly faster.


6. Use updateMany() for Bulk Updates

Instead of

for(const id of ids){

    await db.updateOne(...)

}

Use

await db.updateMany(UserModel,{
    filter:{
        status:false
    },
    update:{
        $set:{
            status:true
        }
    }
});

7. Populate Only When Needed

Populate performs additional queries.

Use it only when referenced data is required.

populate:"company_id"

instead of populating every reference.


8. Keep Filters Simple

Good

filter:{
    company_id:id,
    status:true
}

Avoid deeply nested queries unless necessary.


9. Use Aggregation for Reports

Instead of processing thousands of records in JavaScript,

use MongoDB Aggregation.

const report=await db.aggregate(UserModel,{
    group_content:{
        _id:"$city",
        total:{
            $sum:1
        }
    }
});

10. Use findOne() for Single Documents

Instead of

const users=await db.find(...);

use

const user=await db.findOne(...);

when only one document is expected.


11. Handle Errors

Always use try/catch.

try{

    const users=await db.find(UserModel);

}
catch(err){

    console.error(err);

}

12. Prefer Async/Await

Recommended

const users=await db.find(UserModel);

instead of nested Promise chains.


13. Keep Business Logic Outside Queries

Good

const users=await db.find(UserModel,{
    filter:{
        status:true
    }
});

Business logic should remain inside services/controllers rather than query helpers.


14. Use Plain Responses for New Projects

New applications should use the default plain Mongoose response.

const users=await db.find(UserModel);

Use

response:"users"

only when maintaining compatibility with existing applications.


15. Upgrade Gradually

All legacy APIs remain available.

You can migrate one module at a time without changing your entire application.

This makes upgrading safe even for large production systems.


Changelog

v1.2.2

Added

  • Modern MongoDB inspired API.
  • find()
  • findOne()
  • findPopulate()
  • distinct()
  • create()
  • createMany()
  • updateOne()
  • updateMany()
  • deleteOne()
  • deleteMany()
  • aggregate()
  • aggregateFetch()
  • findOneAndUpdate()

Improved

  • Cleaner method names.
  • Simplified options object.
  • Automatic option normalization.
  • Automatic _id conversion from string to ObjectId.
  • Better pagination handling.
  • Better projection support.
  • Better populate support.
  • Improved aggregate helpers.
  • Improved TypeScript definitions.
  • Improved README with complete examples.

Fixed

  • Pagination issues when page was 0.
  • Better handling of empty result sets.
  • Improved update response handling.
  • Improved delete response handling.
  • Better aggregate pagination.

Compatibility

  • Fully backward compatible with all legacy methods.
  • Existing projects require no code changes.
  • Legacy APIs continue to work.

v1.2.0

  • Initial release of the modern API.
  • Introduced wrapper methods over legacy functions.
  • Added option normalization.
  • Added TypeScript support.
  • Improved package structure.

v1.1.x

  • Legacy Pinaka Mongo helper functions.
  • Response wrapper support.
  • Aggregate helpers.
  • Populate helpers.
  • CRUD helper methods.

Future Roadmap

The goal of pnk-node-mongo is to become a complete MongoDB utility library that reduces boilerplate while keeping the API clean, flexible, and production-ready.

Planned Features

Repository Pattern

const users = await UserRepository.find({
    filter: {
        status: true
    }
});

Fluent Query Builder

const users = await db
    .query(User)
    .where({
        status: true
    })
    .sort({
        name: 1
    })
    .limit(10)
    .page(1)
    .find();

Transactions

await db.transaction(async (session) => {

    await db.create(User, userData, {
        session
    });

    await db.updateOne(Account, {
        filter: {
            _id: accountId
        },
        update: {
            balance: 1000
        },
        options: {
            session
        }
    });

});

Bulk Operations

await db.bulkWrite(User, [
    {
        insertOne: {
            document: user
        }
    },
    {
        updateOne: {
            filter: {
                _id: id
            },
            update: {
                $set: {
                    active: true
                }
            }
        }
    }
]);

Soft Delete Support

await db.softDelete(User, {
    _id: userId
});

Restore Deleted Records

await db.restore(User, {
    _id: userId
});

Audit Logging

Automatically store:

  • Created By
  • Created On
  • Updated By
  • Updated On
  • Deleted By
  • Deleted On
  • IP Address
  • Device Information

Query Middleware

db.beforeFind((filter) => {
    filter.company_id = currentCompany;
});

db.afterFind((data) => {
    return data;
});

Validation Layer

await db.create(User, data, {
    validate: true
});

Schema Helpers

timestamps();
softDelete();
auditFields();
companyFilter();

Performance Metrics

  • Query execution time
  • Slow query logging
  • Query statistics
  • Database performance metrics

Better TypeScript Support

  • Strong typing
  • Generic models
  • Better IntelliSense
  • Auto-completion

Plugin System

db.use(CachePlugin);

db.use(AuditPlugin);

db.use(EncryptionPlugin);

Caching

  • Redis support
  • In-memory cache
  • Automatic cache invalidation

AI Query Generator

Convert natural language into MongoDB queries.

Example:

Find all active customers from Bangalore created this month

{
    filter: {
        city: "Bangalore",
        status: true,
        created_on: {
            $gte: ...
        }
    }
}

More MongoDB Features

  • Atlas Search
  • Vector Search
  • Time Series Collections
  • Change Streams
  • GridFS Helpers
  • Full Text Search
  • Geospatial Queries

Community Contributions

Feature requests, bug reports, improvements, and pull requests are always welcome.

If you have ideas to improve pnk-node-mongo, feel free to open an issue or submit a pull request.

Together, we can make pnk-node-mongo one of the easiest and most productive MongoDB helper libraries for Node.js.


Contributing

Thank you for your interest in contributing to pnk-node-mongo.

Contributions of all kinds are welcome, including bug fixes, new features, documentation improvements, examples, performance enhancements, and TypeScript improvements.


Reporting Bugs

If you find a bug, please create an issue containing:

  • Package version
  • Node.js version
  • Mongoose version
  • MongoDB version
  • Operating System
  • Steps to reproduce
  • Expected behavior
  • Actual behavior
  • Sample code (if possible)

Feature Requests

Feature requests are always welcome.

Before creating a request:

  • Check existing issues.
  • Explain the use case.
  • Provide sample code if possible.

Development Setup

Clone the repository.

git clone https://github.com/YOUR_USERNAME/pnk-node-mongo.git

Install dependencies.

npm install

Build the package.

npm run build

Run your project using the local package.


Pull Requests

Before submitting a Pull Request:

  • Follow existing coding style.
  • Keep changes focused.
  • Update documentation when necessary.
  • Add examples for new features.
  • Test your changes thoroughly.

Coding Guidelines

  • Use modern JavaScript (ES2020+)
  • Prefer async/await
  • Keep functions small and reusable
  • Avoid breaking backward compatibility
  • Write readable and maintainable code

Project Goals

The primary goals of this library are:

  • Simple API
  • Minimal boilerplate
  • High performance
  • Clean architecture
  • Production-ready code
  • Full backward compatibility

Ways to Contribute

You can contribute by:

  • Reporting bugs
  • Improving documentation
  • Adding examples
  • Improving TypeScript definitions
  • Optimizing performance
  • Suggesting new features
  • Fixing issues
  • Improving test coverage

Code of Conduct

Please be respectful and constructive while contributing.

We welcome developers of all experience levels and appreciate every contribution that helps improve the project.


Thank You ❤️

Every contribution, whether it's a bug report, documentation improvement, or code enhancement, helps make pnk-node-mongo better for the community.

Thank you for your support!


FAQ

Is this library a replacement for Mongoose?

No.

pnk-node-mongo is built on top of Mongoose and simplifies common CRUD operations while remaining fully compatible with Mongoose models.


Can I still use Mongoose methods?

Yes.

You can freely mix Mongoose and pnk-node-mongo.

await User.find();

await db.find(User);

Does it support TypeScript?

Yes.

Type definitions are included.


Is backward compatibility maintained?

Yes.

All legacy Pnk* methods continue to work.


Can I use aggregation?

Yes.

Both aggregate helper methods are supported.


Does it support populate?

Yes.

Use findPopulate().


Does it work with MongoDB Atlas?

Yes.

Since it uses Mongoose internally, it works with MongoDB Atlas without additional configuration.


Can I use transactions?

Yes.

Transactions can be passed through Mongoose session options.


Which Node.js versions are supported?

Node.js 18+

Recommended:

  • Node.js 20+
  • Mongoose | 6.x / 7.x / 8.x |

License

MIT License

Copyright (c) 2026 Pinaka Digital Technologies

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software.

See the LICENSE file for full details.


Acknowledgements

Special thanks to:

  • MongoDB Team
  • Mongoose Team
  • Node.js Community
  • Open Source Contributors

for building the technologies that power this library.


Support

If you encounter any issues or have feature requests:

  • Open a GitHub Issue
  • Submit a Pull Request
  • Share suggestions for improvements

Community feedback helps make pnk-node-mongo better with every release.


Star the Project ⭐

If pnk-node-mongo saves you development time, please consider giving the repository a ⭐ on GitHub.

Your support helps the project grow and encourages future development.

Thank you for using pnk-node-mongo!