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

snapjson

v2.0.0

Published

A simple ORM for Node.js using JSON file

Readme

snapjson

Build Status npm version Size

snapjson is a lightweight NoSQL object-relational mapping (ORM) library for Node.js, written in TypeScript. It allows you to store data in JSON files, with each collection represented as an array of documents.

Table of Contents

Installation

Using npm:

npm install snapjson

Using yarn:

yarn add snapjson

Using pnpm:

pnpm add snapjson

Getting Started

To use the snapjson module, follow these simple steps:

  • For a quick start, we provide CLI commands to configure the database and create collections rapidly. To access the CLI commands, click here.

Importing the SnapJson class

import { SnapJson, createCollection } from "snapjson";

Creating an instance of SnapJson

To use SnapJson, you need to create an instance of the class. You can configure it by passing an options object or by using environment variables.

🔹 Option 1: Using a configuration object

const config = {
  path_db: "db",
};
const orm = new SnapJson(config);

Available Options

| Option | Type | Default | Description | | --------- | ----------------------------------- | --------- | ------------------------------------------------------ | | path_db | string (optional) | "db" | Directory where JSON data will be stored | | splitFile | boolean (optional) | false | If true, each collection is stored in its own file | | encrypted | boolean (optional) | false | It true, data will be encrypted | | secretKey | string (optional) | undefined | Key used for encryption | | salt | string (optional) | undefined | Optional salt for additional encryption security | | mode | string (optional) ("prod" et "dev") | "dev" | Defines the working mode (development or production) |

🔹 Option 1: Using environment variables

SnapJson also supports environment variables for configuration. If environment variables are set, you can instantiate SnapJson without passing any config object.

const orm = new SnapJson();

Available Options

| Variable Name | Default | Description | | ------------------ | ------------- | ------------------------------------------------------------------------------------------- | | SNAPJSON_PATH_DB | "db" | Directory where JSON data will be stored | | SNAPJSON_SPLITFILE | "false" | If true, each collection is stored in its own file | | SNAPJSON_ENCRYPTED | "false" | It true, data will be encrypted | | SNAPJSON_SECRETKEY | " " | Key used for encryption | | SNAPJSON_SALT | " " | Optional salt for additional encryption security | | NODE_ENV | "environment" | Defines the working mode (development or production). values: environment et production |

Defining the data schema

Define your data schema using TypeScript interfaces (the __id property will be added automatically for the primary key):

interface UserSchema {
  name: string;
  email: string;
  password: string;
  age?: number;
}

Creating a collection

// Option 1: Simple collection creation
const collection = await orm.createCollection("user"); // It returns instance of this collection.
console.log(collection); // user

// Option 2: Creating multiple collections at once
const collections = await orm.createCollections(["user", "teacher"]);
console.log(collections); // [ 'user', 'teacher' ]

// Option 3: Creating collection with unique key
const collection = await orm.createCollection({
  collectionName: "user",
  uniqueKeys: ["email"], // This defines all properties that will be unique.
});

Collection Configuration Options

| Property | Description | | -------------- | ----------------------------------------------------------- | | collectionName | Name of the collection | | uniqueKeys | Defines all properties that will be unique. | | idStrategy | Defines how document IDs are generated. (uuid et increment) | | createdAt | Date when the document was first created | | updatedAt | Date when the document was last updated. |

Alternatively, you can use a shortcut helper function:

// Instead of orm.createCollection and orm.createCollections, you can use: createCollection function, imported from snapjson.
// createCollection<T>(collection: string | { collectionName: string; uniqueKeys?: Array<keyof T>; }, opts?: {...,force?: boolean}).
const collection = await createCollection("user");

const config = {
  path_db: "id",
  splitFile: true,
  mode: "dev",
};
const collections = await createCollection(["user", "teacher"], config);

Defining a collection

To define a collection, you have three methods available:

Method 1: Using the SnapJson Class

import { SnapJson } from "snapjson";
const config = {
  path_db: "id",
  splitFile: true,
  mode: "dev",
};
const orm = new SnapJson(config);
const usersCollection = await orm.collection<UserSchema>("user");

const usersCollection = await orm.collection<UserSchema>("user", true); // create collection 'user' when it doesn't exist.

This will return an instance of this collection if it exists, otherwise, an error will be thrown.

Method 2: Using shortcut helper function

import { defineCollection } from "snapjson";
const config = {
  path_db: "id",
  splitFile: true,
  mode: "dev",
  force: true, // If true, create collection 'user' when it doesn't exist.
};
const usersCollection = await defineCollection<UserSchema>("user", config);

const usersCollection = await defineCollection<UserSchema>("user", config);

Method 3: Using the Collection Class

import { Collection } from "snapjson";
const config = {
  path_db: "id",
  splitFile: true,
  mode: "dev",
  force: true, // If true, create collection 'user' when it doesn't exist.
};
const usersCollection = new Collection<UserSchema>("user", config);

The key difference between these methods is in their verification timing. The first and second method check if the collection exists before instantiation, while the third method checks upon execution of query methods such as find, findOne, and more.

Removing a collection

const collection = await orm.removeCollection("user");
console.log(collection); // user
const collections = await orm.removeCollection(["teacher", "student"]);
console.log(collections); // [ 'teacher', 'student' ]

// Or
// removeCollection(collections: string | string[], opts?: {...,force?: boolean})
await removeCollection("user");
await removeCollection(["teacher", "student"]);

Query Methods

Use collection methods for querying:

Inserting documents

const usersCollection = await orm.collection<UserSchema>("user");

// Or

const usersCollection = await defineCollection<UserSchema>("user");

// Inserting one document
const alice = await usersCollection.insertOne({
  email: "[email protected]",
  name: "Alice",
  password: "!13x47dh32",
  age: 25,
});

console.log(alice.toObject());

/*
  {
    email: '[email protected]',
    name: 'Alice',
    password: '!13x47dh32',
    age: 25,
    __id: 1
  }
*/

// Inserting multiple documents at once
const users = await usersCollection.insertMany([
  {
    email: "[email protected]",
    name: "Carole",
    password: "!13x9dnsnv",
    age: 22,
  },
  {
    email: "[email protected]",
    name: "Mary",
    password: "xnjsd7432&8",
    age: 20,
  },
]);

users.forEach((user) => {
  console.log(user.toObject());
});

/*
  {
    email: '[email protected]',
    name: 'Carole',
    password: '!13x9dnsnv',
    age: 22,
    __id: 2
  }
  {
    email: '[email protected]',
    name: 'Mary',
    password: 'xnjsd7432&8',
    age: 20,
    __id: 3
  }
*/

Finding documents

// Finding one document
const carole = await usersCollection.findOne(
  { name: "Carole" },
  { select: ["__id", "age", "email", "name"] }
);
if (carole) console.log(carole.toObject());

/*
  {
    email: '[email protected]',
    name: 'Carole',
    age: 22,
    __id: 2
  }
*/

// Finding documents
const users = await usersCollection.find(
  { age: { $gte: 20 } },
  { select: ["__id", "age", "email", "name"], limit: 3 }
);
users.forEach((user) => {
  console.log(user.toObject());
});

/*
  { __id: 1, age: 25, email: '[email protected]', name: 'Alice' }
  { __id: 2, age: 22, email: '[email protected]', name: 'Carole' }
  { __id: 3, age: 20, email: '[email protected]', name: 'Mary' }
*/

Updating documents

/*
  Before updating:

  {
    email: '[email protected]',
    name: 'Mary',
    password: 'xnjsd7432&8',
    age: 20,
    __id: 3
  }
*/
const data = { age: 21 };
const user = await usersCollection.updateOne(data, { __id: 3 });
if (user) console.log(user.toObject());

/*
  After updating:

  {
    email: '[email protected]',
    name: 'Mary',
    password: 'xnjsd7432&8',
    age: 21, ✔
    __id: 3
  }
*/

Deleting documents

const user = await usersCollection.deleteOne({ __id: 3 });
if (user) console.log(user.toObject());

/*
  {
    email: '[email protected]',
    name: 'Mary',
    password: 'xnjsd7432&8',
    age: 21,
    __id: 3
  }
*/

Document methods

The Document object provides several methods for manipulating the properties of the document:

| Name | Description | | -------- | ------------------------------------------------------------------------------------ | | delete | Deletes the document from the collection. | | save | Saves the changes to the document. | | toJSON | Converts the document into JSON. | | toObject | Converts the document into a plain object. | | update | Updates the document. If the save flag is set to true, the document will be saved. |

const user = await usersCollection.findById(1);

if (user) {
  console.log(user.toObject());
  console.log(user.toJSON());
  user.age = 10;
  await user.save();
  await user.delete();
}

Additional methods

SnapJson class

/*
  - getCollections
  - isExistCollection
  - size
  - pathDB
*/

const collections = await orm.getCollections(); // Returns all collection names available in the database.
console.log(collections); // [ 'user' ]

const isExists = await orm.isExistCollection("user"); // Returns true if the collection exists in the database, otherwise returns false.
console.log(isExists); // true

const databaseSize = await orm.size(); // Returns the size of the database file.
console.log(databaseSize); // 58 KB

console.log(orm.pathDB); // db/

Collection class

/*
  - addUniqueKey
  - getUniqueKeys
  - removeUniqueKey
  - removeUniqueKey
  - removeAllUniqueKeys
  - count
  - size
  - lastInsertId
  - add
  - create
*/

// addUniqueKey
const key = await usersCollection.addUniqueKey("email");
console.log(key); // email

const keys = await usersCollection.addUniqueKey(["email", "name"]);
console.log(key); // [ 'email', 'name' ]

// getUniqueKeys
const keys = await usersCollection.getUniqueKeys();
console.log(keys); // [ 'email', 'name' ]

// removeUniqueKey
const keys = await usersCollection.removeUniqueKey("name");
console.log(keys); // name

// removeAllUniqueKeys
const keys = await usersCollection.removeAllUniqueKeys();
console.log(keys); // [ 'email', 'name' ]

// count
const ct = await usersCollection.count();
console.log(ct); // 3
// Or
await usersCollection.count({ age: { $lte: 30 } });

// size
const collectionSize = await usersCollection.size();
console.log(collectionSize); // 26 KB

// lastInsertId
const id = await usersCollection.lastInsertId();
console.log(id); // 3

// add and create methods are aliases for insertOne method

Command Line Interface (CLI)

SnapJson includes a powerful CLI tool built-in for managing your database configuration, creating and deleting collections, and defining relationships between collections. The CLI is automatically available when you install SnapJson.

Using the CLI

After installing SnapJson, you can use the CLI with:

npx snapjson [command] [flags]

Or if you've installed SnapJson globally:

npm install -g snapjson
snapjson [command] [flags]

Database Configuration

Before using any CLI commands, you need to configure your database.

Initialize Database Configuration

snapjson init

This interactive command will prompt you for:

  • Database path: Where your JSON data files will be stored (default: db)
  • Mode: Development or production mode
  • Encryption: Enable/disable data encryption
  • File splitting: Whether to split data into multiple files
  • Secret key and salt (if encryption is enabled): For securing your data

To use default values without prompts:

snapjson init --yes

Example:

$ snapjson init
? Enter database path (db): mydata
? Select mode (dev/prod): prod
? Enable encryption? (yes/NO): yes
? Enable file splitting? (yes/NO): no
✓ Database configuration saved to .env file

Collection Management

Create Collections

snapjson create -c

or

snapjson c -c

This interactive command prompts for:

  • Collection name: Name of your collection (e.g., users, posts)
  • Unique keys: Fields that must be unique (comma-separated)
  • ID strategy: increment or uuid
  • createdAt field: Auto-add creation timestamp
  • updatedAt field: Auto-add update timestamp

Example:

$ snapjson create -c
=== Create Collection ===
? Enter collection name: users
? Does this collection have unique keys? (yes/NO): yes
? Enter unique keys (comma-separated, e.g., "email,username"): email,username
? ID Strategy - increment or uuid (default: increment): uuid
? Add createdAt field? (yes/NO): yes
? Add updatedAt field? (yes/NO): yes
✓ Collection "users" created successfully!
? Create another collection? (yes/NO): no
✓ All collections created successfully!
Use 'snapjson list --collection' to view all collections

List Collections

snapjson list -c

or

snapjson l -c

Example output:

$ snapjson list -c

=== Collections ===

1. users
2. posts
3. comments

Delete Collections

snapjson delete -c

or

snapjson d -c

You'll be prompted to enter the collection names (space-separated):

Example:

$ snapjson delete -c
? Enter collections to remove ("profile user post ..."): users posts
Collections removed successfully : users, posts

Relation Management

Create Relations

snapjson create -r

or

snapjson c -r

This interactive command prompts for:

  • Target collection: The collection being referenced
  • Source collection: The collection containing the reference
  • Relation type: hasOne, hasMany, or belongsTo
  • Local key: Field in the local collection
  • Foreign key: Field in the related collection
  • Relation field/alias: Name of the relation property
  • Referential actions: CASCADE, SET NULL, RESTRICT, or NO ACTION for delete/update operations

Example:

$ snapjson create -r

Available collections: users, posts, comments

=== Create Relation ===

? Enter target collection name: users
? Enter source collection name: posts
? Relation type (hasOne/hasMany/belongsTo) (default: hasOne): hasOne
? Local key (default: usersId): author_id
? Foreign key: (default: __id): id
? Enter relation field (default: posts): posts
? Enter the referential action when deleting (CASCADE/SET NULL/RESTRICT/NO ACTION) (default: SET NULL): CASCADE
? Enter the referential action when updating (CASCADE/SET NULL/RESTRICT/NO ACTION) (default: CASCADE): CASCADE
✓ Relation created: users -> posts (hasOne)
? Create another relation? (yes/NO): no
✓ All relations created successfully!
Use 'snapjson list --relation' to view all relations

List Relations

snapjson list -r

or

snapjson l -r

Example output:

$ snapjson list -r

=== Relations ===

1. posts belongsTo users
2. comments belongsTo posts
3. users hasMany posts

Delete Relations

snapjson delete -r

or

snapjson d -r

You'll be prompted for:

  • Target collection: The collection referenced in the relation
  • Source collections: The collections containing the references (space-separated)

Example:

$ snapjson delete -r
? Enter target collection name: users
? Enter the names of the source collections ("profile post ..."): posts comments
Relations removed successfully : posts, comments

Help and Version

Display available commands:

snapjson --help

or

snapjson -h

Display the installed version:

snapjson --version

or

snapjson -v

Complete Workflow Example

Here's a step-by-step example of setting up a blog database:

# 1. Initialize database
snapjson init --yes

# 2. Create collections
snapjson create -c
# Create: users, posts, comments

# 3. List created collections
snapjson list -c

# 4. Define relationships
snapjson create -r
# Create: posts belongsTo users, comments belongsTo posts, users hasMany posts

# 5. View all relationships
snapjson list -r

# 6. Use in your code

Then use it in your TypeScript/JavaScript code:

import { SnapJson } from "snapjson";

const orm = new SnapJson();

// Collections are now configured and ready to use
const users = await orm.collection("users");
const posts = await orm.collection("posts");
const comments = await orm.collection("comments");

// Create a new user
await users.add({ name: "John", email: "[email protected]" });

// Create a post with relation to user
await posts.add({ title: "My Blog", author_id: 1 });

Advanced Usage

Defining Relations Between Collection

Overview

SnapJson now supports joining collections, enabling developers to define relationships between JSON-based data structures, similar to joins in relational databases – but tailored for NoSQL-like flexibility.

With this feature, you can link documents across collections using a reference key, retrieve related data effortlessly, and keep your logic clean and organized. Whether you're working with embedded references or external collection links, SnapJson makes it easy to simulate relational behavior in a JSON environment.

This is especially useful for scenarios where your data is stored in separate collections but logically connected – like users and posts, categories and products, or invoices and clients.

Relations Syntax

You can define relations at collection creation using the relations property.

relations: {
  collectionName: string;       // Name of the related collection (e.g., "user")
  localKey?: string;            // Field in the current collection (default: `{parent name}Id`)
  foreignKey?: string;          // Field in the related collection (default: "__id")
  as?: string;                  // Alias name for the relation (default: parent name)
  relationType?: "belongsTo" | "hasOne" | "hasMany"; // Default: "hasOne"
  onUpdate?: "cascade" | "set null" | "restrict" | "no action"; // Default: "cascade"
  onDelete?: "cascade" | "set null" | "restrict" | "no action"; // Default: "set null"
}
await orm.createCollection({
  collectionName: "profile",
  relations: [
    {
      collectionName: "user",
      localKey: "userId",
      foreignKey: "__id",
      as: "user",
      relationType: "belongsTo",
      onUpdate: "cascade",
      onDelete: "set null",
    },
  ],
});

// Here, profile belongs to user

Supported Relation Types

| Type | Description | | --------- | ------------------------------------------------------------- | | belongsTo | The current collection belongs to a parent collection | | hasOne | The current collection has one related child collection | | hasMany | The current collection has multiple related child collections |

Relation Options

| Option | Behavior | | -------- | ------------------------------------------------------------------------------------- | | cascade | Automatically updates or deletes the related collection | | set null | Sets the related collection to null on delete or sets the local key to null on update | | restrict | Prevents deletion or update if there's relation | | no acton | No automatic behavior |

Default:
  • onUpdate: "cascade"
  • onDelete: "set null"

Using Relation in Queries

Once defined, you can retrieve related data using include property.

await usersCollection.find( {}, { include : "profile" );

/*
  [
    {
      __id: "1",
      name: "Alice",
      profile: {
        __id: "1",
        bio: "Software Engineer",
        userId: "1",
      },
    },
  ];
*/

This will include the related user object under the key user (or whatever alias was defined in as)

Note: the joined documents is embedded directly as object. hasMany joins will embed an array of objects instead.

hasMany Join Example

await studentsCollection.find(
  {},
  {
    include: {
      collectionName: "student",
      limit: 10,
    },
  }
);

/*
  [
    {
      __id: "1",
      name: "Alice",
      marks: [
        {
          __id: "1",
          userId: "1",
          info: 7,
          maths: 8,
          geo: 6,
        },
        {},...
      ],
    },
  ];
*/

Using Query Operators

Operators are special symbols or keywords that allow you to carry out mathematical or logical operations. snapjson provides a large number of operators to help you build complex queries.

snapjson offers the following query operator types:

  • Comparison
  • Logical
  • Array

Comparison Operators

snapjson comparison operators can be used to compare values in a document. The following table contains the common comparison operators.

| Operators | Description | | --------- | --------------------------------------------------------------- | | $eq | Matches values that are equal to the given value. | | $ne | Matches values that are not equal to the given value. | | $gt | Matches if values are greater than the given value. | | $gte | Matches if values are greater than or equal to the given value. | | $lt | Matches if values are less than the given value. | | $lte | Matches if values are less than or equal to the given value. | | $in | Matches any of the values in an array. | | $nin | Matches none of the values specified in an array. |

$eq Operator

In this example, we retrieve the document with the exact id value 2.

const user = await usersCollection.findOne({ __id: { $eq: 2 } });
if (user) console.log(user.toObject());

/*
  {
    email: '[email protected]',
    name: 'Carole',
    password: '!13x9dnsnv',
    age: 22,
    __id: 2
}
$ne Operator

Suppose we have a collection of students, and we need to find all documents whose age field is not equal to 40:

await studentsCollection.find({ age: { $ne: 40 } }))

/*
  [
    {
      __id: 1,
      name: "Gonzalez Estrada",
      gender: "male",
      age: 39,
      email: "[email protected]",
    },
    {
      __id: 2,
      name: "Burris Leon",
      gender: "male",
      age: 37,
      email: "[email protected]",
    },
    {
      __id: 3,
      name: "Maryanne Wagner",
      gender: "female",
      age: 32,
      email: "[email protected]",
    },
  ];
*/
$gt Operator

In this example, we retrieve the documents where the age field is greater than 35:

await studentsCollection.find({ age: { $gt: 35 } });

/*
  [
    {
      __id: 1,
      name: "Gonzalez Estrada",
      gender: "male",
      age: 39,
      email: "[email protected]",
    },
    {
      __id: 2,
      name: "Burris Leon",
      gender: "male",
      age: 37,
      email: "[email protected]",
    },
    {
      __id: 6,
      name: "Alyce Strickland",
      gender: "female",
      age: 40,
      email: "[email protected]",
    },
  ];
*/
$lt Operator

Let’s find the documents whose age field is less than 35:

await studentsCollection.find({ age: { $lt: 35 } });

/*
  [
    {
      __id: 3,
      name: "Maryanne Wagner",
      gender: "female",
      age: 32,
      email: "[email protected]",
    },
    {
      __id: 4,
      name: "Fay Fowler",
      gender: "female",
      age: 24,
      email: "[email protected]",
    },
    {
      __id: 5,
      name: "Angeline Conner",
      gender: "female",
      age: 20,
      email: "[email protected]",
    },
  ];
*/
$gte Operator

Suppose we have a collection of students, and we need to find all documents whose age field is greater than or equal to 35.

await studentsCollection.find({ age: { $gte: 35 } });

/*
  [
    {
      __id: 24,
      name: "Linda Henderson",
      gender: "female",
      age: 35, ✔
      email: "[email protected]",
    },
    {
      __id: 26,
      name: "Beryl Howe",
      gender: "female",
      age: 40,
      email: "[email protected]",
    },
    {
      __id: 28,
      name: "Russell Mcclure",
      gender: "male",
      age: 39,
      email: "[email protected]",
    },
  ];
*/
$lte Operator

Let’s find the documents whose age field is less than or equal to 35.

await studentsCollection.find({ age: { $lte: 35 } });

/*
  [
    {
      __id: 29,
      name: "Mcmahon Wilkinson",
      gender: "male",
      age: 23,
      email: "[email protected]",
    },
    {
      __id: 30,
      name: "Nita Knapp",
      gender: "female",
      age: 35, ✔
      email: "[email protected]",
    },
    {
      __id: 31,
      name: "Sampson Morrison",
      gender: "male",
      age: 26,
      email: "[email protected]",
    },
  ];
*/
$in Operator

The following query returns documents where the age field contains the given values.

await studentsCollection.find({ age: { $in: [20, 30, 40] } });

/*
  [
    {
      __id: 70,
      name: "Hilary Watson",
      gender: "female",
      age: 20,
      email: "[email protected]",
    },
    {
      __id: 82,
      name: "Estrada Ramsey",
      gender: "male",
      age: 30,
      email: "[email protected]",
    },
    {
      __id: 91,
      name: "Lela Howard",
      gender: "female",
      age: 40,
      email: "[email protected]",
    },
  ];
*/
$nin Operator

In this example, we retrieve the documents where the age field doesn't contain the given values.

await studentsCollection.find({ age: { $nin: [20, 30, 40] } });

/*
 [
    {
      __id: 1,
      name: "Gonzalez Estrada",
      gender: "male",
      age: 39,
      email: "[email protected]",
    },
    {
      __id: 2,
      name: "Burris Leon",
      gender: "male",
      age: 37,
      email: "[email protected]",
    },
    {
      __id: 3,
      name: "Maryanne Wagner",
      gender: "female",
      age: 32,
      email: "[email protected]",
    },
  ];
*/

Logical Operators

Logical operators are used to filter data based on given conditions. They provide a way to combine multiple conditions.

snapjson provides two logical operators: $or and $and.

| Operator | Description | | -------- | ----------------------------------------------------------------------------------------------------- | | $and | Joins two or more queries with a logical AND and returns the documents that match all the conditions. | | $or | Join two or more queries with a logical OR and return the documents that match either query. |

$and Operator

Find documents that match both the following conditions:

◻ gender is equal to "male" ◻ age is between 20 and 25

await studentsCollection.find({
  $and: [
    { gender: "male" },
    { age: { $gte: 20, $lte: 25 } },
  ]
})

/*
  [
    {
      __id: 13,
      name: "Martinez Potts",
      gender: "male",
      age: 20,
      email: "[email protected]",
    },
    {
      __id: 22,
      name: "Patton Molina",
      gender: "male",
      age: 22,
      email: "[email protected]",
    },
    {
      __id: 27,
      name: "Key Mercado",
      gender: "male",
      age: 25,
      email: "[email protected]",
    },
  ];
/*
$or Operator

Find documents that match either of the following conditions:

◻ gender is equal to "male" or "female"

await studentsCollection.find({
  $or: [{ gender: "male" }, { gender: "female" }],
});

/*
  [
    {
      __id: 1,
      name: "Gonzalez Estrada",
      gender: "male",
      age: 39,
      email: "[email protected]",
    },
    {
      __id: 2,
      name: "Burris Leon",
      gender: "male",
      age: 37,
      email: "[email protected]",
    },
    {
      __id: 3,
      name: "Maryanne Wagner",
      gender: "female",
      age: 32,
      email: "[email protected]",
    },
  ];
*/

Array Operators

snapjson provides several operators for searching arrays. Here are the array operators provided by snapjson.

| Operator | Description | | ----------- | ------------------------------------------------------------------------------------------ | | $eq | Matches arrays that equal to the specified array. e.g. [1, 2, 3] == [1, 2, 3] | | $ne | Matches arrays that do not equal to the specified array. e.g. [1, 2, 3] !== [3, 2, 1] | | $contains | Matches arrays that contain all the specified values. | | $nocontains | Matches arrays that do not contain all the specified values. |

Basic query

Suppose we have a collection of shoes, and we need to find all shoes that have 3 colors: the first color is red, second is white, and third is green.

await shoesCollection.find({ colors: ["red", "white", "green"] });

/*
  [
    {
      __id: 231,
      price: '$88',
      colors: [ 'red', 'white', 'green' ],
      rate: 4,
      nb_view: 836,
      madeIn: 'Peru'
    }
  ]
*/

// Note that arr1 and arr2 are not equal; on the other hand, arr3 and arr4 are equal.

const arr1 = [1, 2, 3];
const arr2 = [3, 2, 1];

const arr3 = [1, [2], 3];
const arr4 = [1, [2], 3];
$eq and $ne operators

We have already explained in detail their use cases. They are used in the same way for the arrays.

$contains operator

Suppose we have a collection of shoes, and we need to find all shoes that have at least 2 colors: white and black.

await shoesCollection.find({ colors: { $contains: ["black", "white"] } });

/*
  [
    {
      __id: 361,
      price: "$48",
      colors: ["blue", "black", "white"],
      rate: 0,
      nb_view: 163,
      madeIn: "Spain",
    },
    {
      __id: 411,
      price: "$50",
      colors: ["black", "green", "white"],
      rate: 4,
      nb_view: 100,
      madeIn: "Korea (South)",
    },
    {
      __id: 611,
      price: "$79",
      colors: ["white", "black"],
      rate: 4,
      nb_view: 784,
      madeIn: "Comoros",
    },
  ];
*/
$nocontains operator

In this example, we retrieve the documents where the colors field doesn't contain white and black colors at once..

await shoesCollection.find({ colors: { $nocontains: ["black", "white"] } });

/*
  [
    {
      __id: 971,
      price: "$54",
      colors: ["blue", "brown", "green"],
      rate: 0,
      nb_view: 692,
      madeIn: "Indonesia",
    },
    {
      __id: 981,
      price: "$44",
      colors: ["yellow", "white"], => Here, white color is alone.
      rate: 4,
      nb_view: 632,
      madeIn: "Malawi",
    },
    {
      __id: 991,
      price: "$45",
      colors: ["cyan", "purple", "red"],
      rate: 4,
      nb_view: 955,
      madeIn: "Malta",
    },
  ];
*/

await shoesCollection.find({ colors: { $nocontains: "white" } });

/*
  [
    {
      __id: 971,
      price: "$54",
      colors: ["blue", "brown", "green"],
      rate: 0,
      nb_view: 692,
      madeIn: "Indonesia",
    },
    {
      __id: 991,
      price: "$45",
      colors: ["cyan", "purple", "red"],
      rate: 4,
      nb_view: 955,
      madeIn: "Malta",
    },
  ];
*/

Working with Regular Expressions

snapjson supports regular expressions for string-based queries. You can use regular expressions with various operators to search for patterns within string.

await studentsCollection.find({ email: /.com$/ });
// $eq
await studentsCollection.find({ email: { $eq: /.com$/ } });
// $ne
await studentsCollection.find({ email: { $ne: /.com$/ } });
// $in
await studentsCollection.find({ email: { $in: [/.com$/, /.org$/] } });
// $nin
await studentsCollection.find({ email: { $nin: [/.com$/, /.org$/] } });
// $contains
await shoesCollection.find({ colors: { $contains: [/re/, "cyan"] } });

/*
  [
    {
      __id: 631,
      price: "$91",
      colors: ["white", "green", "cyan"],
      rate: 0,
      nb_view: 817,
      madeIn: "Armenia",
    },
    {
      __id: 721,
      price: "$11",
      colors: ["red", "blue", "cyan"],
      rate: 1,
      nb_view: 849,
      madeIn: "Moldova",
    },
    {
      __id: 991,
      price: "$45",
      colors: ["cyan", "green", "red"],
      rate: 4,
      nb_view: 955,
      madeIn: "Malta",
    },
  ];
*/

Reporting Issues

If you encounter any issues, have questions, or want to contribute to the project, please visit the GitHub repository and open an issue.

License

This project is licensed under the MIT License.