Files
awesome-cheatsheets/databases/mongoose.js
Ehab-24 aa488b84d3 feat - mongoose cheatsheet [in progress]
Notes:
 - Schema
 - Model
 - Promises
 - Aggregation
2023-03-24 17:13:05 +05:00

246 lines
6.2 KiB
JavaScript

/* *****************************************************************
* Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.
* Mongoose supports both promises and callbacks.
* ****************************************************************/
// Import Mongoose
const mongoose = require("mongoose");
/* *****************************************************************
List of Mongoose Data Types:
String
Number
Date
Buffer
Boolean
Mixed
ObjectId
Array
Decimal128
Map
Schema
UUID
******************************************************************/
/* *****************************************************************
* Schema
* A schema is a blueprint for a model.
* It defines the structure of the document, default values, validators, etc.
* ****************************************************************/
// Define schema for the a collection
const productSchema = new mongoose.Schema({
name: {
type: String,
immutable: true, // This field cannot be changed after creation
},
price: {
type: Number,
min: 0, // Minimum value is 0
max: 10000, // Maximum value is 10000
required: true, // Not specifying a required field will result in validation error
},
category: {
type: String,
enum: ["fruit", "vegetable", "dairy"], // Only these values are allowed for 'category'
},
tags: [
// Array of String
{
type: String,
minLength: 2, // Minimum length of a single tag is 2
maxlength: 10, // Maximum length of a single tag is 10
},
],
createdAt: {
type: Date,
// WRONG!
// default: Date.now(), // This results in the current date being set (as a static value) when the schema is compiled
// Correct!
default: () => Date.now(), // We instead use a getter function that returns the current date when called
},
});
// Create a model from the schema
const Product = mongoose.model("Product", productSchema);
// We can now use the model to create new documents in the 'products' collection
/* *****************************************************************
* Promises
* ****************************************************************/
Product.create({
name: "guava",
price: 10,
category: "fruit",
tags: ["green", "sweet", "fresh"],
});
Product.insertMany([
{
name: "apple",
price: 5,
category: "fruit",
tags: ["red", "sweet"],
},
{
name: "banana",
price: 3,
category: "fruit",
tags: ["yellow", "sweet"],
},
{
name: "broccoli",
price: 2,
category: "vegetable",
tags: ["green", "healthy"],
},
{
name: "milk",
price: 4,
category: "dairy",
tags: ["white", "healthy"],
},
]);
Product.find(); // Get documents in 'product' colelction
Product.find({ name: "guava" }); // Get documents where name = 'guava'
Product.find({ price: { $gt: 5, $lt: 10 } }); // Get documents where 5 < price < 10
Product.find({ name: "banana" }).select({ name: 1, price: 1 }); // Get documents where name = 'banana' and only return name and price
Product.countDocuments({ category: "vegetables" }); // Get count of documents where category = 'vegetables'
Product.updateOne({ name: "guava" }, { price: 15 }); // Update the price of the document where name = 'guava' to 15
Product.deleteOne({ name: "guava" }); // Delete the document where name = 'guava'
Product.deleteMany({ category: "fruit" }); // Delete all documents where category = 'fruit'
/* *****************************************************************
* Aggregation
* The aggregation pipeline refers to a specific flow of operations that processes, transforms, and returns results.
* In a pipeline, successive operations are informed by the previous result.
* Check out the MongoDB documentation at: https://www.mongodb.com/docs/manual/aggregation/
* ****************************************************************/
// * $match
// The following aggration pipeline returns all products where price > 80 AND price < 120.
let pipeline = [
{
$match: {
price: {
$gt: 80,
$lt: 120,
},
},
},
];
// or you can use:
pipeline = [
{
$match: {
price: {
$and: [{ $gt: 80 }, { $lt: 120 }],
},
},
},
];
// Similarly, you can use $or:
pipeline = [
{
$match: {
category: {
$or: [{ $eq: "fruit" }, { $eq: "vegetable" }],
},
},
},
];
// * $group
// The following aggregation pipeline returns the total number of products created less than a year ago, in each category.
pipeline = [
{
$match: {
date: {
$gte: new Date(new Date().setFullYear(new Date().getFullYear() - 1)),
},
},
},
{
$group: {
_id: "$category",
count: { $sum: 1 },
},
},
];
// * $sort
// The following aggregation pipeline returns top 10 most expensive products.
// Note: The $sort stage must come before $limit.
pipeline = [
{
$sort: {
price: -1,
},
},
{
$limit: 10,
},
];
// * $project
// To get the name and price of all products along with their ObjectId:
pipeline = [
{
$project: {
name: 1,
price: 1,
},
},
];
// or you can exclude all other fields:
pipeline = [
{
$project: {
category: 0, // 0 means exclude
tags: 0,
date: 0,
},
},
];
// Note: You may not use both 0 and 1 in the same projection
// other than _id, which is included by default:
pipeline = [
{
$project: {
_id: 0, // exclude ObjectId as well
name: 1,
price: 1,
},
},
];
// * $unwind
// The following aggregation returns a new document for 'guava' for each of its tags.
pipeline = [
{
$match: {
name: "guava",
},
},
{
$unwind: {
path: "$tags", // Name of array field that we want to unwind
includeArrayIndex: "arrayIndex", // This will add a new field 'arrayIndex' to each document
preserveNullAndEmptyArrays: true, // This will return a document for each tag, even if the 'tags' is null or empty
},
},
];