What is the best way to activate a function for every new document added using Mongoose?

I am seeking a way to activate a function every time an element is added or created in a collection, not when it's merely updated. (Also, I require the ID of the newly created element)

Here is my approach:

schema.pre("save", function() {
    this.$locals.wasNew = this.isNew;
});

schema.post("save", function() {
    if (this.$locals.wasNew) {
        console.log(`User ${this.id} has been created!`);
    }
});

This method works well with calls like this one:

await UserModel.create({
    mail
});

However, it does not work as expected with calls such as this one:

const user = await UserModel.findOneAndUpdate(
    { mail },
    { $set: { mail } },
    { new: true, upsert: true }
);

It appears that the upsert feature fails to trigger the save hook with the isNew boolean set to true.

Could there be an error in my implementation? Is something missing? Or perhaps there is another method to achieve this?

Answer №1

Executing the same code in document.save hooks on both query.findOneAndUpdate is not feasible. The document.save hooks will not be triggered for query methods. More information can be found in link 1 below.

Nevertheless, there are several workarounds available:

  1. Utilize separate methods like findById and save as an alternative to findOneAndUpdate. This approach mimics the functionality of findOneAndUpdate. For further details, refer to reference link 2.

  2. Explore the use of change streams, detailed in reference link 3.

  3. Consider using includeResultMetadata as suggested by @joe, with additional information provided in reference link 4.

To better understand options 2 and 3, refer to the sample code snippet presented below.

const mongoose = require('/mongoose');
const { Schema } = mongoose;

run().catch((error) => console.log(error));
async function run() {
  await mongoose.connect('mongodb://127.0.0.1:27108', { replicaSet: 'rs' });
  const SomeModel = mongoose.model('Somemodel', new Schema({ key1: String }));
  await SomeModel.deleteMany();

  SomeModel.watch().on('change', (data) => {
    if (data.operationType == 'insert') {
      console.log(`change stream, new document, _id: ${data.fullDocument._id}`);
    }
  });

  await new SomeModel({ key1: 'key1 value 1' }).save();
  const doc2 = await SomeModel.findOneAndUpdate(
    { key1: 'xyz' },
    { key1: 'key1 value2' },
    { new: true, upsert: true, includeResultMetadata: true }
  );

  !doc2.lastErrorObject.updatedExisting &&
    console.log(`ResultMetadata, new document, _id: ${doc2.value._id}`);
}

OUTPUT:

change stream, new document, _id: 6643275fdb709107184e999a
ResultMetadata, new document, _id: 6643275f7550f5d65e7ba6a3
change stream, new document, _id: 6643275f7550f5d65e7ba6a3

Links

  1. Notes on findAndUpdate() and Query Middleware

  2. pre, post middleware are not executed on findByIdAndUpdate #964

  3. Change streams

  4. Using includeResultMetadata

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using JavaScript click event to send information to the database

I really need some guidance with JavaScript and ajax. I would appreciate any help on this topic. I am particularly interested in the question here: Updating a MySql database using PHP via an onClick javascript function Specifically, I am intrigued by th ...

What is the reason behind IE7 and IE8 claiming to have 'hasLayout' when in reality it does not possess such a feature?

HTML: <div class="table" > <div class="row" > <span>Table with DIV</span> <span>column2</span> <span>column3</span> </div> <div class="row" > <span>col ...

When passing context to createPage for use in a query, there may be issues if a string is inadvertently converted to a number, causing the query to fail

I am facing an issue with a page creation function that I have implemented. Here is the code snippet: createPage({ context: { productId: String(productId) }, Despite explicitly converting the ID to a string, the page template is still receiving it as a ...

Empty array returned following push operation within Mongoose findById query

Can anyone assist me with inserting objects into an array after a Mongoose FindById operation? I am facing an issue where the array appears empty after the for loop execution. Any help would be greatly appreciated. The code snippet below outlines my appr ...

Activate the extended view of a Material-UI Accordion

When using Accordions to display editable entities, we often want to keep modified entities in the expanded state. Currently, we have had to duplicate functionality by lifting up the expanded state into the accordion wrapper to prevent any controlled <- ...

Is there a way to initiate an AJAX post request with the Authorization header for the initial request using Windows Authentication?

I'm working on a web application that has a video page and a Web API for logging purposes. The events are triggered using an ajax post request: function logAction(actionToLog) { $.ajax({ type: 'POST', url: "/api/v/" + cu ...

Using React to showcase an array of objects in a table with row spanning

I'm facing a challenge with displaying adjustedAmount, paidAmount, and cost type in a table where one row is divided into multiple costs. Can someone help me figure out how to do this? Below is the object I need to work with: const datdfa = [ { ind ...

Having difficulty managing asynchronous functions with the useState hook in React

import React from "react"; import { UserContext } from "./../contexts"; import { removeStoredAuthData, storedAuthIsValid, storeNewAuthData, } from "./../utils/auth"; import { getUserInfos } from "./../api/userAuthen ...

A guide to finding matching data in two collections with mongoose's aggregate method

My quiz application has two schemas: const quizSchema = new mongoose.Schema({ userID: { type: String, required: [true, 'User ID required'] } }); Response Schema - const responseSchema = new mongoose.Schema({ userID: { type: Str ...

Resolving "Module not found: Error: Can't resolve 'url'" issue in Angular 14 while invoking web3 smart contract function

How do I resolve the web3-related errors in my Angular 14 dapp? I attempted to fix the issue by running npm i crypto, npm i http, and more. Every time I try to call a function from a smart contract with code like this.manager = await report.methods.mana ...

Incorporating an HTTP header into d3.json using queue.js

I know that I can include a header in a D3 JSON request by using the following code: d3.json("http://localhost:8080/data") .header("Application-ID", "1") However, I'm uncertain about how to add this header when utilizing queue's defer method. ...

Encountering issues when dynamically altering the material texture in three.js during runtime

Having full control over a material, changing its color at runtime is seamless. However, attempting to change the map texture results in an error. For instance: var materials = mesh.material.materials; materials[index].color.setHex(0xb60430); materials[i ...

Changing the color of a div's text based on its content with CSS

I am facing a challenge in styling the text inside a “div” element using a Javascript function. Initially, when the page loads, these “divs” contain no value. The values of the "divs" will change between "Open" and "Closed" twice a day when the Jav ...

Checking for selected checkboxes in Django admin's action-select using jQuery/JavaScript

In my Django admin project, I want to check if any of the action-select check-boxes have been selected in the change_list.html file using jQuery/JavaScript. Initially, I tried the following code: $(".action-select"); This gave me an array of all the inpu ...

Generate downloadable files dynamically in response to a POST request

I'm exploring the idea of creating a file without actually storing it on the drive, just for the purpose of immediate download within a POST request. const specialRequests = async (req, res, next) => { // POST request ... // processing let ...

Is it possible to assign a property value to an object based on the type of another property?

In this illustrative example: enum Methods { X = 'X', Y = 'Y' } type MethodProperties = { [Methods.X]: { x: string } [Methods.Y]: { y: string } } type Approach = { [method in keyof Method ...

Removing children does not work properly; it only removes half of them

Why am I unable to remove all children if I delete half of them in this code? I keep getting an error saying child is not defined, even though I have declared it. Each node in my code has children spheres (nodes) and edges (lines), but when I try to dele ...

Encountering an issue with MUI 5 where it is unable to access properties of undefined when utilizing makestyles

I recently finished building a react app using MUI-5 and everything was running smoothly. However, I've encountered a strange issue where my app refuses to start and I'm bombarded with multiple MUI errors. These errors started popping up after I ...

The remote server encounters a net::ERR_CONNECTION_CLOSED error when attempting to process a MongoDB document with over seven sub-documents

Currently, I am working on a MEAN project using angular 4.1.0. While everything runs smoothly on my localhost, issues arise when I deploy the project to the server. Specifically, attempting to retrieve a user with more than 8 question-answer pairs trigger ...

Tips on serializing two arrays into JSON format and incorporating them in an AJAX request

I have a task where I need to retrieve all the names and details associated with a specific reference number. To accomplish this, I am using a while loop. However, I am unsure of how to encode these values in JSON format so that I can use them in AJAX for ...