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

Angular: monitoring changes in HTML content within a Component or Directive

I have a situation where I am retrieving HTML content from a REST endpoint using a directive and inserting it into a div element using [innerHTML]. Once this HTML content is rendered, I would like to manipulate it by calling a global function. My approach ...

Error encountered in Typescript: SyntaxError due to an unexpected token 'export' appearing

In my React project, I encountered the need to share models (Typescript interfaces in this case) across 3 separate Typescript projects. To address this, I decided to utilize bit.env and imported all my models to https://bit.dev/model/index/~code, which wor ...

What is the best way to implement a dynamic mask using imask in a React

I have a question regarding the implementation of two masks based on the number of digits. While visually they work correctly, when I submit the form, the first mask is always selected. How can I resolve this issue? My solution involves using imask-react ...

OnDrop event in React is failing to trigger

In my current React + TypeScript project, I am encountering an issue with the onDrop event not working properly. Both onDragEnter and onDragOver functions are functioning as expected. Below is a snippet of the code that I am using: import * as React from ...

What is the best way to implement debouncing for an editor value that is controlled by the parent component?

Custom Editor Component import Editor from '@monaco-editor/react'; import { useDebounce } from './useDebounce'; import { useEffect, useState } from 'react'; type Props = { code: string; onChange: (code: string) => void ...

I'm having trouble with my Typescript file in Vscode - every time I try to edit the css code, all the text turns red. Can someone

Check out this visual representation: [1]: https://i.stack.imgur.com/9yXUJ.png Followed by the corresponding code snippet. export const GlobalStyle = createGlobalStyle` html { height: 100%; } body { background-image: url(${BGImage}); ba ...

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", ...

Deactivating a form field depending on a selected radio button in Angular 2

If I have two radio buttons, with a click function called localClick for the first button to give value 1 and the second button to give value 2. <div class="ui-g-12"><p-radioButton name="group1" value="Local" (click)=localClick(1) label="Local"&g ...

The presence of a method is triggering an Error TS2741 message stating that the property is missing in type

Here is a simplified code snippet that highlights the issue I am facing: class Test { prop1 : boolean prop2 : string method() { } static create(prop1 : boolean, prop2 : string) : Test { let item : Test = { prop1: prop1, prop2: pro ...

What is the reference point for 'this' in Mongoose query middleware and pre-find hooks?

After diving into the world of mongoose query middleware, I've come to realize that using this within a query middleware function actually refers to the query object itself. Despite this knowledge, I still find it challenging to imagine what the quer ...

Executing functions and MongoDB queries within a setTimeout function in a Meteor application

While working on the server side, I am attempting to update a field within my Mongo collection using a callback function as a parameter in a setTimeout function in Meteor. The goal is to create a function that runs at regular intervals to clean up the data ...

What is the correct way to convert a non-observable into an observable?

Can I convert a non-observable into an observable to receive direct image updates without having to refresh the page, but encountering this error: Type 'EntityImage[]' is missing the following properties from type 'Observable<EntityImage ...

Unpacking JSON Objects in Typescript: Working with Private Variables

I have a TypeScript model object called user export class User { constructor( private _name: string, private _email: string ) {} public get name():string { return this._name; } public set name(value:string) { this._name = value; } g ...

Issue with importing in VueJS/TypeScript when using gRPC-Web

I have developed a straightforward VueJS application and am currently grappling with incorporating an example for file upload functionality. The proto file I am utilizing is as follows: syntax = "proto3"; message File { bytes content = 1; } ...

Precise object mapping with Redux and Typescript

In my redux slice, I have defined a MyState interface with the following structure: interface MyState { key1: string, key2: boolean, key3: number, } There is an action named set which has this implementation: set: (state: MyState, action: PayloadAct ...

What is the best way to test a local variable in Angular 2 using karma and jasmine?

I've been working on writing a unit test with jasmine, but I've run into an issue when trying to test a local variable using jasmine. I have successfully tested a global variable in the past, but testing a local variable seems to be more challeng ...

Disabling an anchor using the 'disabled' property is proving to be a challenge for me

I'm attempting to dynamically enable or disable an anchor element based on the user's role. So far, I've tried a few different methods: document.getElementById('myBtn').disabled = true; However, this returns an error: The propert ...

Applying TPS rate to existing API endpoints at the method level within API Gateway using AWS CDK

I have successfully set up a UsagePlan and connected it to an API stage with CDK. However, I am having difficulty implementing method throttling at the API stage for a specific resource path. Despite searching online, I have not been able to find a satis ...

Using `await` inside an if block does not change the type of this expression

Within my code, I have an array containing different user names. My goal is to loop through each name, verify if the user exists in the database, and then create the user if necessary. However, my linter keeps flagging a message stating 'await' h ...

Retrieve and access an array of objects from MongoDB

Assuming I have some data stored in MongoDB as follows - [ { _id: new ObjectId("63608e3c3b74ed27b5bdf6fa"), latitude: 24.3065, hotels: [ { name: "Saunders Oconnor", lat ...