Mastering the proper implementation of OneToMany and ManyToOne relationships in MongoDB involves understanding and utilizing the

I am currently working on setting up a oneToMany, ManyToOne relation method and here is my progress so far (pseudocode provided below). I am using Typegoose which is essentially Mongoose with types. If you are unfamiliar with it, that's okay because this discussion is more about architecture. Specifically, I want to address the "createBook" method. As you can see in the code snippet, I am using nested "await" calls which can be inefficient. I could potentially use promises and end the method by calling

Promise.all(bookQuery, authorQuery)
, but I am facing challenges with error handling. What if one operation fails while the other succeeds? This inconsistency is not ideal (ideally, if one operation fails, the other should rollback any changes it made). How can I efficiently and effectively write the "createBook" method?

class Author extends Typegoose {
  @prop()
  fullName: string;

  @prop({ ref: Book, default: [] })
  books: Ref<Book>[];
}

class Book extends Typegoose {
  @prop()
  title: string;

  @prop({ ref: Author })
  author: Ref<Author>;
}

async createBook(title, authorId): Promise<Book> {
    const book = await new this.bookRepository({
      title,
      author: ObjectId(authorId)
    }).save();

    await this.authorRepository.updateOne(
      { _id: authorId },
      { $push: { books: Types.ObjectId(book.id) } }
    );

    return book;
  }

Answer №1

One approach is as follows:

async createBook(title, authorId): Promise<Book> {
  const book = new this.bookRepository({
    title,
    author: ObjectId(authorId)
  }).save();

  const author = this.authorRepository.updateOne(
    { _id: authorId },
    { $push: { books: Types.ObjectId(book.id) } }
  );
  try {
    await Promise.all([book, author])
    return book;
  } catch (e) {
    console.log(e)
    await Promise.all([
      this.bookRepository.deleteOne({_id: book._id}),
      this.authorRepository.updateOne(
        { _id: authorId },
        { $pull: { books: Types.ObjectId(book.id) } 
      }
    )]
  }
}

Another option is to implement MongoDB Transactions. This feature was introduced in MongoDB version 4.0 and initially restricted to Replica Sets. However, starting from version 4.2, Transactions will also be supported for sharded collections.

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

There was an UnhandledPromiseRejectionWarning that occurred due to a TypeError when attempting to read the property 'unlink' of an undefined value, specifically

I'm having a problem deleting a file based on its id using gridfs. Whenever I attempt to call the delete API, I encounter this error. Controller : let gfs; connect.once("open", () => { gfs = Grid(connect.db, mongoose.mongo); gfs.collection("u ...

What is the best way to create a memoized function in React?

I am currently developing an application using react and typescript, and I am facing a challenge in memoizing a function. const formatData = ( data: number[], gradientFill?: CanvasGradient ): Chart.ChartData => ({ labels: ["a", ...

How can I retrieve the value of a promise in Promise.map?

I am currently working on a project that involves saving data to a database using Mongoose. One specific field in the database is the 'thumbnail' field, which needs to be filled with a base64 converted file after the file is uploaded to the serve ...

php code for verifying the format of MongoDB ids

How can I validate a MongoDB ID from a query string? I want to redirect to another URL if the MongoDB ID is not valid. Here's how to get the query string: if(count($_GET)>0 && $_GET['uid']){ // Get the ID from the query string $qu ...

Switch the Follow/Following button depending on the user's current follow status with the individual

I am currently working on a functionality to toggle between the Follow and Following buttons based on whether the current user is following another individual. I have implemented an NgIF statement in my code, but I am facing challenges in properly checking ...

Alter the class based on the incoming string from the rxjs stream

I have a stream that outputs strings, and based on these strings I want to apply certain classes to a specific tag: If the string is "ok", add class "fa-check" If the string is "loading", add classes "fa-spin" and "fa-spinner" If the string is "error", a ...

Difficulty Resolving Parameter Resolution in Angular 5 Shared Library Module ([object Object], ?, ?)

I'm facing an issue while attempting to integrate a custom shared component library into my Angular application, which has been upgraded from Angular 5 to Angular 4. Unfortunately, I am unable to resolve the problem at hand. The error message I&apos ...

Steps for initiating an Angular 4 project

While most developers have moved on to Angular 5, I was tasked with creating a project using Angular 4. After conducting research for several days, I discovered that downgrading the Angular CLI would allow me to accomplish this. By following this approach, ...

What can you do when encountering the error "Unexpected token" in Node.js?

While attempting to save the Node JS code, I encountered an error message stating 'Parsing error: Unexpected Token'. Please note that Mongo is connected. I have made adjustments to the curly brackets and semicolons, but the issue persists. What ...

"Troubleshooting: Unspecified getInitialProps in Nextjs when passing it to a layout component

Greetings, I am a newcomer to Next.js and facing an issue with passing dynamic properties to the header component. Despite using getInitialProps in Next.js successfully, I encounter the problem of receiving 'UNDEFINED' when these properties are p ...

Tips on changing the date format in Typescript to the desired format

My date string reads as 2016-09-19T18:10:31+0100. Here's what I'm doing: let dateString:string = 2016-09-19T18:10:31+0100; let newDateString:Date = new Date(dateString); The output I'm currently getting is Tue Sep 19 2016 18:10:31 GMT+0530 ...

Retrieving all data from the collections in Mongoose MongoDB

I am currently utilizing MongoDB in conjunction with Mongoose for my project. My goal is to create a database that holds a complete list of countries, each consisting of a name and a collection of cities. Each city will then have an associated list of host ...

Node.js: Managing multiple occurrences of the same event name for testing purposes

When it comes to unit testing using mocha, I am looking for a way to set up an asynchronous queue for handling events. Previously, I used a once() Promise to wait for events like this: import EventEmitter from 'events' import { once } from ' ...

The memory usage of Mongodb exceeds the specified value in the wiredTigercacheSizeGB parameter

Hey there, experts! So, I've got my MongoDB server up and running on my 2GB EC2 instance using this command: mongod --wiredTigerCacheSizeGB=0.5 Here's a peek at my current memory usage: ------------------------------------------------ MALLOC: ...

Angular - optional parameter in route using ngRouter

I have a question regarding using Angular (4) with the @angular/router. I want to be able to include optional parameters in a path style, but am facing some challenges. Currently, my code looks like this: { path: 'cars', component: CarComponent ...

What is the correct way to trigger an event specified as a string parameter in the emit() function?

My current goal is to pass the emit name as a string (for example, 'showComponent') from child to parent. I then want to trigger another emit in the emitAction(callbackName: string) function, and finally execute the showComponent() function. I&a ...

Angular threw an error saying: "Template parse errors: is not a recognized element"

I am attempting to utilize babel standalone within a react application to transpile Angular TypeScript. The transpiling process seems to be successful, however, I encounter an error when trying to import a component and use its selector within the template ...

The border of the Material UI Toggle Button is not appearing

There seems to be an issue with the left border not appearing in the toggle bar below that I created using MuiToggleButton. Any idea what could be causing this? Thank you in advance. view image here view image here Just a note: it works correctly in the ...

After upgrading to version 4.0.0 of typescript-eslint/parser, why is eslint having trouble recognizing JSX or certain react @types as undefined?"

In a large project built with ReactJs, the eslint rules are based on this specific eslint configuration: const DONT_WARN_CI = process.env.NODE_ENV === 'production' ? 0 : 1 module.exports = { ... After upgrading the library "@typescript-es ...

What is the best way to access automatically generated JavaScript variables in TypeScript?

I am currently facing an issue with integrating a Google login API in my React project and I need some help. The problem arises when the user already has an active session, rendering the API unnecessary. The Javascript solution provided is as follows: co ...